#pragma once // // This file is distributed under the MIT License. See LICENSE.md for details. // #include #include #include #include "llvm/Support/YAMLTraits.h" #include "revng/ADT/STLExtras.h" #include "revng/ADT/UpcastablePointer.h" #include "revng/Support/Assert.h" template struct KeyedObjectTraits; template> concept KeyedObjectContainerCompatible = requires(T A) { { Traits::key(A) }; { Traits::fromKey(Traits::key(A)) } -> std::same_as; } && std::is_same_v>; /// Inherit if T is the key of itself template struct IdentityKeyedObjectTraits { static T key(const T &Obj) { return Obj; } static T fromKey(T Obj) { return Obj; } }; /// Trivial specializations template struct KeyedObjectTraits : public IdentityKeyedObjectTraits {}; template<> struct KeyedObjectTraits : public IdentityKeyedObjectTraits {}; template<> struct KeyedObjectTraits : public IdentityKeyedObjectTraits {}; static_assert(KeyedObjectContainerCompatible); template concept KeyedObjectContainer = requires(T &&) { T::KeyedObjectContainerTag; }; namespace revng::detail { template using KOT = KeyedObjectTraits; template using Key = std::decay_t::key(std::declval()))>; } // namespace revng::detail template using DefaultKeyObjectComparator = std::less>; template struct llvm::yaml::SequenceTraits { static size_t size(IO &TheIO, T &Seq) { return Seq.size(); } class Inserter { private: using value_type = typename T::value_type; using KOT = KeyedObjectTraits; using key_type = decltype(KOT::key(std::declval())); private: T &Seq; decltype(Seq.begin()) It; bool IsOutputting; std::optional BatchInserter; value_type Instance; unsigned Index = 0; public: Inserter(IO &TheIO, T &Seq) : Seq(Seq), It(Seq.begin()), IsOutputting(TheIO.outputting()), Instance(KOT::fromKey(key_type())) { if constexpr (std::is_const_v) { revng_assert(IsOutputting); } else { if (not IsOutputting) BatchInserter.emplace(std::move(Seq.batch_insert())); } } decltype(*It) &preflightElement(unsigned I) { revng_assert(Index == I); ++Index; if (IsOutputting) return *(It++); else return Instance; } void postflightElement(unsigned) { if (not IsOutputting) { BatchInserter->insert(Instance); Instance = KOT::fromKey(key_type()); } }; }; };