File indexing completed on 2026-05-10 08:44:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #ifndef LLVM_SUPPORT_FORMAT_H
0023 #define LLVM_SUPPORT_FORMAT_H
0024
0025 #include "llvm/ADT/ArrayRef.h"
0026 #include "llvm/ADT/STLExtras.h"
0027 #include "llvm/ADT/StringRef.h"
0028 #include "llvm/Support/DataTypes.h"
0029 #include <cassert>
0030 #include <cstdio>
0031 #include <optional>
0032 #include <tuple>
0033 #include <utility>
0034
0035 namespace llvm {
0036
0037
0038
0039 class format_object_base {
0040 protected:
0041 const char *Fmt;
0042 ~format_object_base() = default;
0043 format_object_base(const format_object_base &) = default;
0044 virtual void home();
0045
0046
0047 virtual int snprint(char *Buffer, unsigned BufferSize) const = 0;
0048
0049 public:
0050 format_object_base(const char *fmt) : Fmt(fmt) {}
0051
0052
0053
0054
0055 unsigned print(char *Buffer, unsigned BufferSize) const {
0056 assert(BufferSize && "Invalid buffer size!");
0057
0058
0059 int N = snprint(Buffer, BufferSize);
0060
0061
0062 if (N < 0)
0063 return BufferSize * 2;
0064
0065
0066
0067 if (unsigned(N) >= BufferSize)
0068 return N + 1;
0069
0070
0071 return N;
0072 }
0073 };
0074
0075
0076
0077
0078
0079
0080
0081 template <typename... Args> struct validate_format_parameters;
0082 template <typename Arg, typename... Args>
0083 struct validate_format_parameters<Arg, Args...> {
0084 static_assert(std::is_scalar_v<Arg>,
0085 "format can't be used with non fundamental / non pointer type");
0086 validate_format_parameters() { validate_format_parameters<Args...>(); }
0087 };
0088 template <> struct validate_format_parameters<> {};
0089
0090 template <typename... Ts>
0091 class format_object final : public format_object_base {
0092 std::tuple<Ts...> Vals;
0093
0094 template <std::size_t... Is>
0095 int snprint_tuple(char *Buffer, unsigned BufferSize,
0096 std::index_sequence<Is...>) const {
0097 #ifdef _MSC_VER
0098 return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
0099 #else
0100 return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...);
0101 #endif
0102 }
0103
0104 public:
0105 format_object(const char *fmt, const Ts &... vals)
0106 : format_object_base(fmt), Vals(vals...) {
0107 validate_format_parameters<Ts...>();
0108 }
0109
0110 int snprint(char *Buffer, unsigned BufferSize) const override {
0111 return snprint_tuple(Buffer, BufferSize, std::index_sequence_for<Ts...>());
0112 }
0113 };
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 template <typename... Ts>
0125 inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) {
0126 return format_object<Ts...>(Fmt, Vals...);
0127 }
0128
0129
0130 class FormattedString {
0131 public:
0132 enum Justification { JustifyNone, JustifyLeft, JustifyRight, JustifyCenter };
0133 FormattedString(StringRef S, unsigned W, Justification J)
0134 : Str(S), Width(W), Justify(J) {}
0135
0136 private:
0137 StringRef Str;
0138 unsigned Width;
0139 Justification Justify;
0140 friend class raw_ostream;
0141 };
0142
0143
0144
0145
0146 inline FormattedString left_justify(StringRef Str, unsigned Width) {
0147 return FormattedString(Str, Width, FormattedString::JustifyLeft);
0148 }
0149
0150
0151
0152
0153 inline FormattedString right_justify(StringRef Str, unsigned Width) {
0154 return FormattedString(Str, Width, FormattedString::JustifyRight);
0155 }
0156
0157
0158
0159
0160 inline FormattedString center_justify(StringRef Str, unsigned Width) {
0161 return FormattedString(Str, Width, FormattedString::JustifyCenter);
0162 }
0163
0164
0165 class FormattedNumber {
0166 uint64_t HexValue;
0167 int64_t DecValue;
0168 unsigned Width;
0169 bool Hex;
0170 bool Upper;
0171 bool HexPrefix;
0172 friend class raw_ostream;
0173
0174 public:
0175 FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U,
0176 bool Prefix)
0177 : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U),
0178 HexPrefix(Prefix) {}
0179 };
0180
0181
0182
0183
0184
0185
0186
0187 inline FormattedNumber format_hex(uint64_t N, unsigned Width,
0188 bool Upper = false) {
0189 assert(Width <= 18 && "hex width must be <= 18");
0190 return FormattedNumber(N, 0, Width, true, Upper, true);
0191 }
0192
0193
0194
0195
0196
0197
0198
0199
0200 inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width,
0201 bool Upper = false) {
0202 assert(Width <= 16 && "hex width must be <= 16");
0203 return FormattedNumber(N, 0, Width, true, Upper, false);
0204 }
0205
0206
0207
0208
0209
0210
0211
0212 inline FormattedNumber format_decimal(int64_t N, unsigned Width) {
0213 return FormattedNumber(0, N, Width, false, false, false);
0214 }
0215
0216 class FormattedBytes {
0217 ArrayRef<uint8_t> Bytes;
0218
0219
0220
0221 std::optional<uint64_t> FirstByteOffset;
0222 uint32_t IndentLevel;
0223 uint32_t NumPerLine;
0224 uint8_t ByteGroupSize;
0225 bool Upper;
0226 bool ASCII;
0227 friend class raw_ostream;
0228
0229 public:
0230 FormattedBytes(ArrayRef<uint8_t> B, uint32_t IL, std::optional<uint64_t> O,
0231 uint32_t NPL, uint8_t BGS, bool U, bool A)
0232 : Bytes(B), FirstByteOffset(O), IndentLevel(IL), NumPerLine(NPL),
0233 ByteGroupSize(BGS), Upper(U), ASCII(A) {
0234
0235 if (ByteGroupSize > NumPerLine)
0236 ByteGroupSize = NumPerLine;
0237 }
0238 };
0239
0240 inline FormattedBytes
0241 format_bytes(ArrayRef<uint8_t> Bytes,
0242 std::optional<uint64_t> FirstByteOffset = std::nullopt,
0243 uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4,
0244 uint32_t IndentLevel = 0, bool Upper = false) {
0245 return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine,
0246 ByteGroupSize, Upper, false);
0247 }
0248
0249 inline FormattedBytes
0250 format_bytes_with_ascii(ArrayRef<uint8_t> Bytes,
0251 std::optional<uint64_t> FirstByteOffset = std::nullopt,
0252 uint32_t NumPerLine = 16, uint8_t ByteGroupSize = 4,
0253 uint32_t IndentLevel = 0, bool Upper = false) {
0254 return FormattedBytes(Bytes, IndentLevel, FirstByteOffset, NumPerLine,
0255 ByteGroupSize, Upper, true);
0256 }
0257
0258 }
0259
0260 #endif