StreamWriter.h 8.0 KB

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