//===- DiffPrinter.h ------------------------------------------ *- C++ --*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLVM_TOOLS_LLVMPDBDUMP_DIFFPRINTER_H #define LLVM_TOOLS_LLVMPDBDUMP_DIFFPRINTER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include #include namespace std { template <> struct hash { typedef llvm::pdb::PdbRaw_FeatureSig argument_type; typedef std::size_t result_type; result_type operator()(argument_type Item) const { return std::hash{}(uint32_t(Item)); } }; } // namespace std namespace llvm { namespace pdb { class PDBFile; enum class DiffResult { UNSPECIFIED, IDENTICAL, EQUIVALENT, DIFFERENT }; struct IdenticalDiffProvider { template DiffResult compare(const T &Left, const U &Right) { return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::DIFFERENT; } template std::string format(const T &Item, bool Right) { return formatv("{0}", Item).str(); } }; struct EquivalentDiffProvider { template DiffResult compare(const T &Left, const U &Right) { return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::EQUIVALENT; } template std::string format(const T &Item, bool Right) { return formatv("{0}", Item).str(); } }; class DiffPrinter { public: DiffPrinter(uint32_t Indent, StringRef Header, uint32_t PropertyWidth, uint32_t FieldWidth, bool Result, bool Values, raw_ostream &Stream); ~DiffPrinter(); template struct Identical {}; template void print(StringRef Property, const T &Left, const U &Right, Provider P = Provider()) { std::string L = P.format(Left, false); std::string R = P.format(Right, true); DiffResult Result = P.compare(Left, Right); printExplicit(Property, Result, L, R); } void printExplicit(StringRef Property, DiffResult C, StringRef Left, StringRef Right); template void printExplicit(StringRef Property, DiffResult C, const T &Left, const U &Right) { std::string L = formatv("{0}", Left).str(); std::string R = formatv("{0}", Right).str(); printExplicit(Property, C, StringRef(L), StringRef(R)); } template void diffUnorderedArray(StringRef Property, ArrayRef Left, ArrayRef Right) { std::unordered_set LS(Left.begin(), Left.end()); std::unordered_set RS(Right.begin(), Right.end()); std::string Count1 = formatv("{0} element(s)", Left.size()); std::string Count2 = formatv("{0} element(s)", Right.size()); print(std::string(Property) + "s (set)", Count1, Count2); for (const auto &L : LS) { auto Iter = RS.find(L); std::string Text = formatv("{0}", L).str(); if (Iter == RS.end()) { print(Property, Text, "(not present)"); continue; } print(Property, Text, Text); RS.erase(Iter); } for (const auto &R : RS) { auto Iter = LS.find(R); std::string Text = formatv("{0}", R).str(); if (Iter == LS.end()) { print(Property, "(not present)", Text); continue; } print(Property, Text, Text); } } template void diffUnorderedMap(StringRef Property, const StringMap &Left, const StringMap &Right, ValueProvider P = ValueProvider()) { StringMap RightCopy(Right); std::string Count1 = formatv("{0} element(s)", Left.size()); std::string Count2 = formatv("{0} element(s)", Right.size()); print(std::string(Property) + "s (map)", Count1, Count2); for (const auto &L : Left) { auto Iter = RightCopy.find(L.getKey()); if (Iter == RightCopy.end()) { printExplicit(L.getKey(), DiffResult::DIFFERENT, L.getValue(), "(not present)"); continue; } print(L.getKey(), L.getValue(), Iter->getValue(), P); RightCopy.erase(Iter); } for (const auto &R : RightCopy) { printExplicit(R.getKey(), DiffResult::DIFFERENT, "(not present)", R.getValue()); } } void printFullRow(StringRef Text); private: uint32_t tableWidth() const; void printHeaderRow(); void printSeparatorRow(); void newLine(char InitialChar = '|'); void printValue(StringRef Value, DiffResult C, AlignStyle Style, uint32_t Width, bool Force); void printResult(DiffResult Result); bool PrintResult; bool PrintValues; uint32_t Indent; uint32_t PropertyWidth; uint32_t FieldWidth; raw_ostream &OS; }; } // namespace pdb } // namespace llvm #endif