1249259Sdim//===-- StreamWriter.h ----------------------------------------------------===// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim 10249259Sdim#ifndef LLVM_READOBJ_STREAMWRITER_H 11249259Sdim#define LLVM_READOBJ_STREAMWRITER_H 12249259Sdim 13249259Sdim#include "llvm/ADT/ArrayRef.h" 14249259Sdim#include "llvm/ADT/StringRef.h" 15249259Sdim#include "llvm/ADT/SmallVector.h" 16249259Sdim#include "llvm/Support/DataTypes.h" 17249259Sdim#include "llvm/Support/Endian.h" 18249259Sdim#include "llvm/Support/raw_ostream.h" 19249259Sdim#include <algorithm> 20249259Sdim 21249259Sdimusing namespace llvm; 22249259Sdimusing namespace llvm::support; 23249259Sdim 24249259Sdimnamespace llvm { 25249259Sdim 26249259Sdimtemplate<typename T> 27249259Sdimstruct EnumEntry { 28249259Sdim StringRef Name; 29249259Sdim T Value; 30249259Sdim}; 31249259Sdim 32249259Sdimstruct HexNumber { 33249259Sdim // To avoid sign-extension we have to explicitly cast to the appropriate 34249259Sdim // unsigned type. The overloads are here so that every type that is implicitly 35249259Sdim // convertible to an integer (including enums and endian helpers) can be used 36249259Sdim // without requiring type traits or call-site changes. 37249259Sdim HexNumber(int8_t Value) : Value(static_cast<uint8_t >(Value)) { } 38249259Sdim HexNumber(int16_t Value) : Value(static_cast<uint16_t>(Value)) { } 39249259Sdim HexNumber(int32_t Value) : Value(static_cast<uint32_t>(Value)) { } 40249259Sdim HexNumber(int64_t Value) : Value(static_cast<uint64_t>(Value)) { } 41249259Sdim HexNumber(uint8_t Value) : Value(Value) { } 42249259Sdim HexNumber(uint16_t Value) : Value(Value) { } 43249259Sdim HexNumber(uint32_t Value) : Value(Value) { } 44249259Sdim HexNumber(uint64_t Value) : Value(Value) { } 45249259Sdim uint64_t Value; 46249259Sdim}; 47249259Sdim 48249259Sdimraw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value); 49249259Sdim 50249259Sdimclass StreamWriter { 51249259Sdimpublic: 52249259Sdim StreamWriter(raw_ostream &OS) 53249259Sdim : OS(OS) 54249259Sdim , IndentLevel(0) { 55249259Sdim } 56249259Sdim 57249259Sdim void flush() { 58249259Sdim OS.flush(); 59249259Sdim } 60249259Sdim 61249259Sdim void indent(int Levels = 1) { 62249259Sdim IndentLevel += Levels; 63249259Sdim } 64249259Sdim 65249259Sdim void unindent(int Levels = 1) { 66249259Sdim IndentLevel = std::max(0, IndentLevel - Levels); 67249259Sdim } 68249259Sdim 69249259Sdim void printIndent() { 70249259Sdim for (int i = 0; i < IndentLevel; ++i) 71249259Sdim OS << " "; 72249259Sdim } 73249259Sdim 74249259Sdim template<typename T> 75249259Sdim HexNumber hex(T Value) { 76249259Sdim return HexNumber(Value); 77249259Sdim } 78249259Sdim 79249259Sdim template<typename T, typename TEnum> 80249259Sdim void printEnum(StringRef Label, T Value, 81249259Sdim ArrayRef<EnumEntry<TEnum> > EnumValues) { 82249259Sdim StringRef Name; 83249259Sdim bool Found = false; 84249259Sdim for (size_t i = 0; i < EnumValues.size(); ++i) { 85249259Sdim if (EnumValues[i].Value == Value) { 86249259Sdim Name = EnumValues[i].Name; 87249259Sdim Found = true; 88249259Sdim break; 89249259Sdim } 90249259Sdim } 91249259Sdim 92249259Sdim if (Found) { 93249259Sdim startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n"; 94249259Sdim } else { 95249259Sdim startLine() << Label << ": " << hex(Value) << "\n"; 96249259Sdim } 97249259Sdim } 98249259Sdim 99249259Sdim template<typename T, typename TFlag> 100249259Sdim void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag> > Flags, 101249259Sdim TFlag EnumMask = TFlag(0)) { 102249259Sdim typedef EnumEntry<TFlag> FlagEntry; 103249259Sdim typedef SmallVector<FlagEntry, 10> FlagVector; 104249259Sdim FlagVector SetFlags; 105249259Sdim 106249259Sdim for (typename ArrayRef<FlagEntry>::const_iterator I = Flags.begin(), 107249259Sdim E = Flags.end(); I != E; ++I) { 108249259Sdim if (I->Value == 0) 109249259Sdim continue; 110249259Sdim 111249259Sdim bool IsEnum = (I->Value & EnumMask) != 0; 112249259Sdim if ((!IsEnum && (Value & I->Value) == I->Value) || 113249259Sdim (IsEnum && (Value & EnumMask) == I->Value)) { 114249259Sdim SetFlags.push_back(*I); 115249259Sdim } 116249259Sdim } 117249259Sdim 118249259Sdim std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); 119249259Sdim 120249259Sdim startLine() << Label << " [ (" << hex(Value) << ")\n"; 121249259Sdim for (typename FlagVector::const_iterator I = SetFlags.begin(), 122249259Sdim E = SetFlags.end(); 123249259Sdim I != E; ++I) { 124249259Sdim startLine() << " " << I->Name << " (" << hex(I->Value) << ")\n"; 125249259Sdim } 126249259Sdim startLine() << "]\n"; 127249259Sdim } 128249259Sdim 129249259Sdim template<typename T> 130249259Sdim void printFlags(StringRef Label, T Value) { 131249259Sdim startLine() << Label << " [ (" << hex(Value) << ")\n"; 132249259Sdim uint64_t Flag = 1; 133249259Sdim uint64_t Curr = Value; 134249259Sdim while (Curr > 0) { 135249259Sdim if (Curr & 1) 136249259Sdim startLine() << " " << hex(Flag) << "\n"; 137249259Sdim Curr >>= 1; 138249259Sdim Flag <<= 1; 139249259Sdim } 140249259Sdim startLine() << "]\n"; 141249259Sdim } 142249259Sdim 143249259Sdim void printNumber(StringRef Label, uint64_t Value) { 144249259Sdim startLine() << Label << ": " << Value << "\n"; 145249259Sdim } 146249259Sdim 147249259Sdim void printNumber(StringRef Label, uint32_t Value) { 148249259Sdim startLine() << Label << ": " << Value << "\n"; 149249259Sdim } 150249259Sdim 151249259Sdim void printNumber(StringRef Label, uint16_t Value) { 152249259Sdim startLine() << Label << ": " << Value << "\n"; 153249259Sdim } 154249259Sdim 155249259Sdim void printNumber(StringRef Label, uint8_t Value) { 156249259Sdim startLine() << Label << ": " << unsigned(Value) << "\n"; 157249259Sdim } 158249259Sdim 159249259Sdim void printNumber(StringRef Label, int64_t Value) { 160249259Sdim startLine() << Label << ": " << Value << "\n"; 161249259Sdim } 162249259Sdim 163249259Sdim void printNumber(StringRef Label, int32_t Value) { 164249259Sdim startLine() << Label << ": " << Value << "\n"; 165249259Sdim } 166249259Sdim 167249259Sdim void printNumber(StringRef Label, int16_t Value) { 168249259Sdim startLine() << Label << ": " << Value << "\n"; 169249259Sdim } 170249259Sdim 171249259Sdim void printNumber(StringRef Label, int8_t Value) { 172249259Sdim startLine() << Label << ": " << int(Value) << "\n"; 173249259Sdim } 174249259Sdim 175249259Sdim template<typename T> 176249259Sdim void printHex(StringRef Label, T Value) { 177249259Sdim startLine() << Label << ": " << hex(Value) << "\n"; 178249259Sdim } 179249259Sdim 180249259Sdim template<typename T> 181249259Sdim void printHex(StringRef Label, StringRef Str, T Value) { 182249259Sdim startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; 183249259Sdim } 184249259Sdim 185249259Sdim void printString(StringRef Label, StringRef Value) { 186249259Sdim startLine() << Label << ": " << Value << "\n"; 187249259Sdim } 188249259Sdim 189249259Sdim void printString(StringRef Label, const std::string &Value) { 190249259Sdim startLine() << Label << ": " << Value << "\n"; 191249259Sdim } 192249259Sdim 193249259Sdim template<typename T> 194249259Sdim void printNumber(StringRef Label, StringRef Str, T Value) { 195249259Sdim startLine() << Label << ": " << Str << " (" << Value << ")\n"; 196249259Sdim } 197249259Sdim 198249259Sdim void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 199249259Sdim printBinaryImpl(Label, Str, Value, false); 200249259Sdim } 201249259Sdim 202249259Sdim void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 203249259Sdim ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 204249259Sdim Value.size()); 205249259Sdim printBinaryImpl(Label, Str, V, false); 206249259Sdim } 207249259Sdim 208249259Sdim void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 209249259Sdim printBinaryImpl(Label, StringRef(), Value, false); 210249259Sdim } 211249259Sdim 212249259Sdim void printBinary(StringRef Label, ArrayRef<char> Value) { 213249259Sdim ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 214249259Sdim Value.size()); 215249259Sdim printBinaryImpl(Label, StringRef(), V, false); 216249259Sdim } 217249259Sdim 218249259Sdim void printBinary(StringRef Label, StringRef Value) { 219249259Sdim ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 220249259Sdim Value.size()); 221249259Sdim printBinaryImpl(Label, StringRef(), V, false); 222249259Sdim } 223249259Sdim 224249259Sdim void printBinaryBlock(StringRef Label, StringRef Value) { 225249259Sdim ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 226249259Sdim Value.size()); 227249259Sdim printBinaryImpl(Label, StringRef(), V, true); 228249259Sdim } 229249259Sdim 230249259Sdim raw_ostream& startLine() { 231249259Sdim printIndent(); 232249259Sdim return OS; 233249259Sdim } 234249259Sdim 235249259Sdim raw_ostream& getOStream() { 236249259Sdim return OS; 237249259Sdim } 238249259Sdim 239249259Sdimprivate: 240249259Sdim template<typename T> 241249259Sdim static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) { 242249259Sdim return lhs.Name < rhs.Name; 243249259Sdim } 244249259Sdim 245249259Sdim void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, 246249259Sdim bool Block); 247249259Sdim 248249259Sdim raw_ostream &OS; 249249259Sdim int IndentLevel; 250249259Sdim}; 251249259Sdim 252249259Sdimstruct DictScope { 253249259Sdim DictScope(StreamWriter& W, StringRef N) : W(W) { 254249259Sdim W.startLine() << N << " {\n"; 255249259Sdim W.indent(); 256249259Sdim } 257249259Sdim 258249259Sdim ~DictScope() { 259249259Sdim W.unindent(); 260249259Sdim W.startLine() << "}\n"; 261249259Sdim } 262249259Sdim 263249259Sdim StreamWriter& W; 264249259Sdim}; 265249259Sdim 266249259Sdimstruct ListScope { 267249259Sdim ListScope(StreamWriter& W, StringRef N) : W(W) { 268249259Sdim W.startLine() << N << " [\n"; 269249259Sdim W.indent(); 270249259Sdim } 271249259Sdim 272249259Sdim ~ListScope() { 273249259Sdim W.unindent(); 274249259Sdim W.startLine() << "]\n"; 275249259Sdim } 276249259Sdim 277249259Sdim StreamWriter& W; 278249259Sdim}; 279249259Sdim 280249259Sdim} // namespace llvm 281249259Sdim 282249259Sdim#endif 283