diff --git a/include/oi/IntrospectionResult.h b/include/oi/IntrospectionResult.h index 4bf25f3..13c87b9 100644 --- a/include/oi/IntrospectionResult.h +++ b/include/oi/IntrospectionResult.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -52,6 +53,13 @@ class IntrospectionResult { std::optional next_; std::vector type_path_; + // This field could be more space efficient as these strings are primarily + // empty. They are used when the string isn't stored in the .rodata section, + // currently when performing key capture. It needs reference stability as we + // keep views in type_path_. A std::unique_ptr would be an + // improvement but it isn't copyable. A string type with size fixed at + // construction would also be good. + std::list dynamic_type_path_; }; IntrospectionResult(std::vector buf, exporters::inst::Inst inst); diff --git a/include/oi/exporters/Json.h b/include/oi/exporters/Json.h index 0015e28..31aa808 100644 --- a/include/oi/exporters/Json.h +++ b/include/oi/exporters/Json.h @@ -28,7 +28,7 @@ class Json { void print(const IntrospectionResult&); void print(IntrospectionResult::const_iterator& it, - IntrospectionResult::const_iterator end); + IntrospectionResult::const_iterator& end); void setPretty(bool pretty) { pretty_ = pretty; diff --git a/oi/IntrospectionResult.cpp b/oi/IntrospectionResult.cpp index 9c5c844..e44d740 100644 --- a/oi/IntrospectionResult.cpp +++ b/oi/IntrospectionResult.cpp @@ -19,6 +19,7 @@ #include #include +#include #include template @@ -41,6 +42,7 @@ IntrospectionResult::const_iterator::operator++() { using U = std::decay_t; if constexpr (std::is_same_v) { type_path_.pop_back(); + dynamic_type_path_.pop_back(); return operator++(); } else { // reference wrapper @@ -65,6 +67,40 @@ IntrospectionResult::const_iterator::operator++() { handler( *next_, [this](auto i) { stack_.emplace(i); }, parsed); } + + std::string& new_name = dynamic_type_path_.emplace_back(std::visit( + [](const auto& d) -> std::string { + using V = std::decay_t; + if constexpr (std::is_same_v) { + std::string out = "["; + out.reserve(d.size() + 2); + out += d; + out += "]"; + return out; + } else if constexpr (std::is_same_v) { + std::stringstream out; + out << '[' << reinterpret_cast(d.p) << ']'; + return out.str(); + } else if constexpr (std::is_same_v) { + std::string out = "["; + out += std::to_string(d.n); + out += ']'; + return out; + } else if constexpr (std::is_same_v) { + return ""; + } else { + static_assert(always_false_v, "missing variant"); + } + }, + next_->data)); + if (!new_name.empty()) { + type_path_.back() = new_name; + next_->type_path.back() = new_name; + next_->name = new_name; + } + for (auto it = ty.fields.rbegin(); it != ty.fields.rend(); ++it) { stack_.emplace(*it); } diff --git a/oi/exporters/Json.cpp b/oi/exporters/Json.cpp index 2654252..ad2590e 100644 --- a/oi/exporters/Json.cpp +++ b/oi/exporters/Json.cpp @@ -48,16 +48,17 @@ Json::Json(std::ostream& out) : out_(out) { void Json::print(const IntrospectionResult& r) { auto begin = r.cbegin(); - return print(begin, r.cend()); + auto end = r.cend(); + return print(begin, end); } void Json::print(IntrospectionResult::const_iterator& it, - IntrospectionResult::const_iterator end) { - std::vector firstTypePath = it->type_path; + IntrospectionResult::const_iterator& end) { + const auto firstTypePathSize = it->type_path.size(); - const auto indent = pretty_ ? makeIndent(firstTypePath.size()) : ""; + const auto indent = pretty_ ? makeIndent(firstTypePathSize) : ""; const auto lastIndent = - pretty_ ? makeIndent(std::max(firstTypePath.size(), 1UL) - 1) : ""; + pretty_ ? makeIndent(std::max(firstTypePathSize, 1UL) - 1) : ""; const auto* tab = pretty_ ? " " : ""; const auto* space = pretty_ ? " " : ""; const auto* endl = pretty_ ? "\n" : ""; @@ -66,7 +67,7 @@ void Json::print(IntrospectionResult::const_iterator& it, bool first = true; while (it != end) { - if (it->type_path.size() < firstTypePath.size()) { + if (it->type_path.size() < firstTypePathSize) { // no longer a sibling, must be a sibling of the type we're printing break; } @@ -127,7 +128,7 @@ void Json::print(IntrospectionResult::const_iterator& it, } out_ << tab << "\"members\":" << space; - if (++it != end && it->type_path.size() > firstTypePath.size()) { + if (++it != end && it->type_path.size() > firstTypePathSize) { print(it, end); } else { out_ << "[]" << endl; @@ -135,7 +136,7 @@ void Json::print(IntrospectionResult::const_iterator& it, out_ << indent << "}"; } - if (firstTypePath.size() == 1) { + if (firstTypePathSize == 1) { out_ << endl << ']' << endl; } else { out_ << endl << lastIndent << tab << ']' << endl; diff --git a/test/integration/capture_keys.toml b/test/integration/capture_keys.toml index c2f9fe2..341dc50 100644 --- a/test/integration/capture_keys.toml +++ b/test/integration/capture_keys.toml @@ -55,21 +55,21 @@ class FixedAllocator { "typePath": ["a0"], "members": [ { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[1]", + "typePath": ["a0","[1]"], "data": 1, "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[1]","key"]}, + {"name": "value", "typePath": ["a0","[1]","value"]} ] }, { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[3]", + "typePath": ["a0","[3]"], "data": 3, "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[3]","key"]}, + {"name": "value", "typePath": ["a0","[3]","value"]} ] } ] @@ -92,21 +92,21 @@ class FixedAllocator { "typePath": ["a0"], "members": [ { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[abc]", + "typePath": ["a0","[abc]"], "data": "abc", "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[abc]","key"]}, + {"name": "value", "typePath": ["a0","[abc]","value"]} ] }, { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[hohoho]", + "typePath": ["a0","[hohoho]"], "data": "hohoho", "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[hohoho]","key"]}, + {"name": "value", "typePath": ["a0","[hohoho]","value"]} ] } ] @@ -125,21 +125,21 @@ class FixedAllocator { "typePath": ["a0"], "members": [ { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[1]", + "typePath": ["a0","[1]"], "data": 1, "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[1]","key"]}, + {"name": "value", "typePath": ["a0","[1]","value"]} ] }, { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[3]", + "typePath": ["a0","[3]"], "data": 3, "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[3]","key"]}, + {"name": "value", "typePath": ["a0","[3]","value"]} ] } ] @@ -165,21 +165,21 @@ class FixedAllocator { "typePath": ["a0"], "members": [ { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[0x300020]", + "typePath": ["a0","[0x300020]"], "data": "0x300020", "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[0x300020]","key"]}, + {"name": "value", "typePath": ["a0","[0x300020]","value"]} ] }, { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[0x301020]", + "typePath": ["a0","[0x301020]"], "data": "0x301020", "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value"]} + {"name": "key", "typePath": ["a0","[0x301020]","key"]}, + {"name": "value", "typePath": ["a0","[0x301020]","value"]} ] } ] @@ -207,22 +207,22 @@ class FixedAllocator { "typePath": ["a0"], "members": [ { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[123]", + "typePath": ["a0","[123]"], "data": 123, "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, + {"name": "key", "typePath": ["a0","[123]","key"]}, { "name": "value", - "typePath": ["a0","[]","value"], + "typePath": ["a0","[123]","value"], "members": [ { "name": "[]", - "typePath": ["a0","[]","value","[]"], + "typePath": ["a0","[123]","value","[]"], "NOT":"data", "members": [ - {"name": "key", "typePath": ["a0","[]","value","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value","[]","value"]} + {"name": "key", "typePath": ["a0","[123]","value","[]","key"]}, + {"name": "value", "typePath": ["a0","[123]","value","[]","value"]} ] } ] @@ -230,31 +230,31 @@ class FixedAllocator { ] }, { - "name": "[]", - "typePath": ["a0","[]"], + "name": "[456]", + "typePath": ["a0","[456]"], "data": 456, "members": [ - {"name": "key", "typePath": ["a0","[]","key"]}, + {"name": "key", "typePath": ["a0","[456]","key"]}, { "name": "value", - "typePath": ["a0","[]","value"], + "typePath": ["a0","[456]","value"], "members": [ { "name": "[]", - "typePath": ["a0","[]","value","[]"], + "typePath": ["a0","[456]","value","[]"], "NOT":"data", "members": [ - {"name": "key", "typePath": ["a0","[]","value","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value","[]","value"]} + {"name": "key", "typePath": ["a0","[456]","value","[]","key"]}, + {"name": "value", "typePath": ["a0","[456]","value","[]","value"]} ] }, { "name": "[]", - "typePath": ["a0","[]","value","[]"], + "typePath": ["a0","[456]","value","[]"], "NOT":"data", "members": [ - {"name": "key", "typePath": ["a0","[]","value","[]","key"]}, - {"name": "value", "typePath": ["a0","[]","value","[]","value"]} + {"name": "key", "typePath": ["a0","[456]","value","[]","key"]}, + {"name": "value", "typePath": ["a0","[456]","value","[]","value"]} ] } ] @@ -283,21 +283,21 @@ class FixedAllocator { "typePath": ["a0","captureMyKeys"], "members": [ { - "name": "[]", - "typePath": ["a0","captureMyKeys","[]"], + "name": "[1]", + "typePath": ["a0","captureMyKeys","[1]"], "data": 1, "members": [ - {"name": "key", "typePath": ["a0","captureMyKeys","[]","key"]}, - {"name": "value", "typePath": ["a0","captureMyKeys","[]","value"]} + {"name": "key", "typePath": ["a0","captureMyKeys","[1]","key"]}, + {"name": "value", "typePath": ["a0","captureMyKeys","[1]","value"]} ] }, { - "name": "[]", - "typePath": ["a0","captureMyKeys","[]"], + "name": "[3]", + "typePath": ["a0","captureMyKeys","[3]"], "data": 3, "members": [ - {"name": "key", "typePath": ["a0","captureMyKeys","[]","key"]}, - {"name": "value", "typePath": ["a0","captureMyKeys","[]","value"]} + {"name": "key", "typePath": ["a0","captureMyKeys","[3]","key"]}, + {"name": "value", "typePath": ["a0","captureMyKeys","[3]","value"]} ] } ]