173 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- 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 <list>
 | |
| #include <unordered_set>
 | |
| 
 | |
| namespace std {
 | |
| template <> struct hash<llvm::pdb::PdbRaw_FeatureSig> {
 | |
|   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>{}(uint32_t(Item));
 | |
|   }
 | |
| };
 | |
| } // namespace std
 | |
| 
 | |
| namespace llvm {
 | |
| namespace pdb {
 | |
| 
 | |
| class PDBFile;
 | |
| 
 | |
| enum class DiffResult { UNSPECIFIED, IDENTICAL, EQUIVALENT, DIFFERENT };
 | |
| 
 | |
| struct IdenticalDiffProvider {
 | |
|   template <typename T, typename U>
 | |
|   DiffResult compare(const T &Left, const U &Right) {
 | |
|     return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::DIFFERENT;
 | |
|   }
 | |
| 
 | |
|   template <typename T> std::string format(const T &Item, bool Right) {
 | |
|     return formatv("{0}", Item).str();
 | |
|   }
 | |
| };
 | |
| 
 | |
| struct EquivalentDiffProvider {
 | |
|   template <typename T, typename U>
 | |
|   DiffResult compare(const T &Left, const U &Right) {
 | |
|     return (Left == Right) ? DiffResult::IDENTICAL : DiffResult::EQUIVALENT;
 | |
|   }
 | |
| 
 | |
|   template <typename T> 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 <typename T, typename U> struct Identical {};
 | |
| 
 | |
|   template <typename Provider = IdenticalDiffProvider, typename T, typename U>
 | |
|   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 <typename T, typename U>
 | |
|   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 <typename T, typename U>
 | |
|   void diffUnorderedArray(StringRef Property, ArrayRef<T> Left,
 | |
|                           ArrayRef<U> Right) {
 | |
|     std::unordered_set<T> LS(Left.begin(), Left.end());
 | |
|     std::unordered_set<U> 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 <typename ValueProvider = IdenticalDiffProvider, typename T,
 | |
|             typename U>
 | |
|   void diffUnorderedMap(StringRef Property, const StringMap<T> &Left,
 | |
|                         const StringMap<U> &Right,
 | |
|                         ValueProvider P = ValueProvider()) {
 | |
|     StringMap<U> 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
 |