StreamWriter.h revision dce4a407a24b04eebc6a376f8e62b41aaa7b071f
1//===-- StreamWriter.h ----------------------------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef LLVM_READOBJ_STREAMWRITER_H 11#define LLVM_READOBJ_STREAMWRITER_H 12 13#include "llvm/ADT/ArrayRef.h" 14#include "llvm/ADT/SmallVector.h" 15#include "llvm/ADT/StringRef.h" 16#include "llvm/Support/DataTypes.h" 17#include "llvm/Support/Endian.h" 18#include "llvm/Support/raw_ostream.h" 19#include <algorithm> 20 21using namespace llvm; 22using namespace llvm::support; 23 24namespace llvm { 25 26template<typename T> 27struct EnumEntry { 28 StringRef Name; 29 T Value; 30}; 31 32struct HexNumber { 33 // To avoid sign-extension we have to explicitly cast to the appropriate 34 // unsigned type. The overloads are here so that every type that is implicitly 35 // convertible to an integer (including enums and endian helpers) can be used 36 // without requiring type traits or call-site changes. 37 HexNumber(int8_t Value) : Value(static_cast<uint8_t >(Value)) { } 38 HexNumber(int16_t Value) : Value(static_cast<uint16_t>(Value)) { } 39 HexNumber(int32_t Value) : Value(static_cast<uint32_t>(Value)) { } 40 HexNumber(int64_t Value) : Value(static_cast<uint64_t>(Value)) { } 41 HexNumber(uint8_t Value) : Value(Value) { } 42 HexNumber(uint16_t Value) : Value(Value) { } 43 HexNumber(uint32_t Value) : Value(Value) { } 44 HexNumber(uint64_t Value) : Value(Value) { } 45 uint64_t Value; 46}; 47 48raw_ostream &operator<<(raw_ostream &OS, const HexNumber& Value); 49 50class StreamWriter { 51public: 52 StreamWriter(raw_ostream &OS) 53 : OS(OS) 54 , IndentLevel(0) { 55 } 56 57 void flush() { 58 OS.flush(); 59 } 60 61 void indent(int Levels = 1) { 62 IndentLevel += Levels; 63 } 64 65 void unindent(int Levels = 1) { 66 IndentLevel = std::max(0, IndentLevel - Levels); 67 } 68 69 void printIndent() { 70 for (int i = 0; i < IndentLevel; ++i) 71 OS << " "; 72 } 73 74 template<typename T> 75 HexNumber hex(T Value) { 76 return HexNumber(Value); 77 } 78 79 template<typename T, typename TEnum> 80 void printEnum(StringRef Label, T Value, 81 ArrayRef<EnumEntry<TEnum> > EnumValues) { 82 StringRef Name; 83 bool Found = false; 84 for (const auto &EnumItem : EnumValues) { 85 if (EnumItem.Value == Value) { 86 Name = EnumItem.Name; 87 Found = true; 88 break; 89 } 90 } 91 92 if (Found) { 93 startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n"; 94 } else { 95 startLine() << Label << ": " << hex(Value) << "\n"; 96 } 97 } 98 99 template<typename T, typename TFlag> 100 void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag> > Flags, 101 TFlag EnumMask = TFlag(0)) { 102 typedef EnumEntry<TFlag> FlagEntry; 103 typedef SmallVector<FlagEntry, 10> FlagVector; 104 FlagVector SetFlags; 105 106 for (const auto &Flag : Flags) { 107 if (Flag.Value == 0) 108 continue; 109 110 bool IsEnum = (Flag.Value & EnumMask) != 0; 111 if ((!IsEnum && (Value & Flag.Value) == Flag.Value) || 112 (IsEnum && (Value & EnumMask) == Flag.Value)) { 113 SetFlags.push_back(Flag); 114 } 115 } 116 117 std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>); 118 119 startLine() << Label << " [ (" << hex(Value) << ")\n"; 120 for (const auto &Flag : SetFlags) { 121 startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n"; 122 } 123 startLine() << "]\n"; 124 } 125 126 template<typename T> 127 void printFlags(StringRef Label, T Value) { 128 startLine() << Label << " [ (" << hex(Value) << ")\n"; 129 uint64_t Flag = 1; 130 uint64_t Curr = Value; 131 while (Curr > 0) { 132 if (Curr & 1) 133 startLine() << " " << hex(Flag) << "\n"; 134 Curr >>= 1; 135 Flag <<= 1; 136 } 137 startLine() << "]\n"; 138 } 139 140 void printNumber(StringRef Label, uint64_t Value) { 141 startLine() << Label << ": " << Value << "\n"; 142 } 143 144 void printNumber(StringRef Label, uint32_t Value) { 145 startLine() << Label << ": " << Value << "\n"; 146 } 147 148 void printNumber(StringRef Label, uint16_t Value) { 149 startLine() << Label << ": " << Value << "\n"; 150 } 151 152 void printNumber(StringRef Label, uint8_t Value) { 153 startLine() << Label << ": " << unsigned(Value) << "\n"; 154 } 155 156 void printNumber(StringRef Label, int64_t Value) { 157 startLine() << Label << ": " << Value << "\n"; 158 } 159 160 void printNumber(StringRef Label, int32_t Value) { 161 startLine() << Label << ": " << Value << "\n"; 162 } 163 164 void printNumber(StringRef Label, int16_t Value) { 165 startLine() << Label << ": " << Value << "\n"; 166 } 167 168 void printNumber(StringRef Label, int8_t Value) { 169 startLine() << Label << ": " << int(Value) << "\n"; 170 } 171 172 template <typename T_> 173 void printList(StringRef Label, const SmallVectorImpl<T_> &List) { 174 startLine() << Label << ": ["; 175 bool Comma = false; 176 for (const auto &Item : List) { 177 if (Comma) 178 OS << ", "; 179 OS << Item; 180 Comma = true; 181 } 182 OS << "]\n"; 183 } 184 185 template<typename T> 186 void printHex(StringRef Label, T Value) { 187 startLine() << Label << ": " << hex(Value) << "\n"; 188 } 189 190 template<typename T> 191 void printHex(StringRef Label, StringRef Str, T Value) { 192 startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n"; 193 } 194 195 void printString(StringRef Label, StringRef Value) { 196 startLine() << Label << ": " << Value << "\n"; 197 } 198 199 void printString(StringRef Label, const std::string &Value) { 200 startLine() << Label << ": " << Value << "\n"; 201 } 202 203 template<typename T> 204 void printNumber(StringRef Label, StringRef Str, T Value) { 205 startLine() << Label << ": " << Str << " (" << Value << ")\n"; 206 } 207 208 void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) { 209 printBinaryImpl(Label, Str, Value, false); 210 } 211 212 void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) { 213 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 214 Value.size()); 215 printBinaryImpl(Label, Str, V, false); 216 } 217 218 void printBinary(StringRef Label, ArrayRef<uint8_t> Value) { 219 printBinaryImpl(Label, StringRef(), Value, false); 220 } 221 222 void printBinary(StringRef Label, ArrayRef<char> Value) { 223 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 224 Value.size()); 225 printBinaryImpl(Label, StringRef(), V, false); 226 } 227 228 void printBinary(StringRef Label, StringRef Value) { 229 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 230 Value.size()); 231 printBinaryImpl(Label, StringRef(), V, false); 232 } 233 234 void printBinaryBlock(StringRef Label, StringRef Value) { 235 ArrayRef<uint8_t> V(reinterpret_cast<const uint8_t*>(Value.data()), 236 Value.size()); 237 printBinaryImpl(Label, StringRef(), V, true); 238 } 239 240 raw_ostream& startLine() { 241 printIndent(); 242 return OS; 243 } 244 245 raw_ostream& getOStream() { 246 return OS; 247 } 248 249private: 250 template<typename T> 251 static bool flagName(const EnumEntry<T>& lhs, const EnumEntry<T>& rhs) { 252 return lhs.Name < rhs.Name; 253 } 254 255 void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value, 256 bool Block); 257 258 raw_ostream &OS; 259 int IndentLevel; 260}; 261 262struct DictScope { 263 DictScope(StreamWriter& W, StringRef N) : W(W) { 264 W.startLine() << N << " {\n"; 265 W.indent(); 266 } 267 268 ~DictScope() { 269 W.unindent(); 270 W.startLine() << "}\n"; 271 } 272 273 StreamWriter& W; 274}; 275 276struct ListScope { 277 ListScope(StreamWriter& W, StringRef N) : W(W) { 278 W.startLine() << N << " [\n"; 279 W.indent(); 280 } 281 282 ~ListScope() { 283 W.unindent(); 284 W.startLine() << "]\n"; 285 } 286 287 StreamWriter& W; 288}; 289 290} // namespace llvm 291 292#endif 293