File indexing completed on 2025-01-18 10:12:42
0001
0002
0003
0004
0005
0006 #pragma once
0007
0008 #include <cctype>
0009 #include <spdlog/common.h>
0010
0011 #if defined(__has_include)
0012 # if __has_include(<version>)
0013 # include <version>
0014 # endif
0015 #endif
0016
0017 #if __cpp_lib_span >= 202002L
0018 # include <span>
0019 #endif
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 namespace spdlog {
0040 namespace details {
0041
0042 template<typename It>
0043 class dump_info
0044 {
0045 public:
0046 dump_info(It range_begin, It range_end, size_t size_per_line)
0047 : begin_(range_begin)
0048 , end_(range_end)
0049 , size_per_line_(size_per_line)
0050 {}
0051
0052
0053 It get_begin() const
0054 {
0055 return begin_;
0056 }
0057 It get_end() const
0058 {
0059 return end_;
0060 }
0061 size_t size_per_line() const
0062 {
0063 return size_per_line_;
0064 }
0065
0066 private:
0067 It begin_, end_;
0068 size_t size_per_line_;
0069 };
0070 }
0071
0072
0073 template<typename Container>
0074 inline details::dump_info<typename Container::const_iterator> to_hex(const Container &container, size_t size_per_line = 32)
0075 {
0076 static_assert(sizeof(typename Container::value_type) == 1, "sizeof(Container::value_type) != 1");
0077 using Iter = typename Container::const_iterator;
0078 return details::dump_info<Iter>(std::begin(container), std::end(container), size_per_line);
0079 }
0080
0081 #if __cpp_lib_span >= 202002L
0082
0083 template<typename Value, size_t Extent>
0084 inline details::dump_info<typename std::span<Value, Extent>::iterator> to_hex(
0085 const std::span<Value, Extent> &container, size_t size_per_line = 32)
0086 {
0087 using Container = std::span<Value, Extent>;
0088 static_assert(sizeof(typename Container::value_type) == 1, "sizeof(Container::value_type) != 1");
0089 using Iter = typename Container::iterator;
0090 return details::dump_info<Iter>(std::begin(container), std::end(container), size_per_line);
0091 }
0092
0093 #endif
0094
0095
0096 template<typename It>
0097 inline details::dump_info<It> to_hex(const It range_begin, const It range_end, size_t size_per_line = 32)
0098 {
0099 return details::dump_info<It>(range_begin, range_end, size_per_line);
0100 }
0101
0102 }
0103
0104 namespace
0105 #ifdef SPDLOG_USE_STD_FORMAT
0106 std
0107 #else
0108 fmt
0109 #endif
0110 {
0111
0112 template<typename T>
0113 struct formatter<spdlog::details::dump_info<T>, char>
0114 {
0115 const char delimiter = ' ';
0116 bool put_newlines = true;
0117 bool put_delimiters = true;
0118 bool use_uppercase = false;
0119 bool put_positions = true;
0120 bool show_ascii = false;
0121
0122
0123 template<typename ParseContext>
0124 SPDLOG_CONSTEXPR_FUNC auto parse(ParseContext &ctx) -> decltype(ctx.begin())
0125 {
0126 auto it = ctx.begin();
0127 while (it != ctx.end() && *it != '}')
0128 {
0129 switch (*it)
0130 {
0131 case 'X':
0132 use_uppercase = true;
0133 break;
0134 case 's':
0135 put_delimiters = false;
0136 break;
0137 case 'p':
0138 put_positions = false;
0139 break;
0140 case 'n':
0141 put_newlines = false;
0142 show_ascii = false;
0143 break;
0144 case 'a':
0145 if (put_newlines)
0146 {
0147 show_ascii = true;
0148 }
0149 break;
0150 }
0151
0152 ++it;
0153 }
0154 return it;
0155 }
0156
0157
0158 template<typename FormatContext, typename Container>
0159 auto format(const spdlog::details::dump_info<Container> &the_range, FormatContext &ctx) -> decltype(ctx.out())
0160 {
0161 SPDLOG_CONSTEXPR const char *hex_upper = "0123456789ABCDEF";
0162 SPDLOG_CONSTEXPR const char *hex_lower = "0123456789abcdef";
0163 const char *hex_chars = use_uppercase ? hex_upper : hex_lower;
0164
0165 #if !defined(SPDLOG_USE_STD_FORMAT) && FMT_VERSION < 60000
0166 auto inserter = ctx.begin();
0167 #else
0168 auto inserter = ctx.out();
0169 #endif
0170
0171 int size_per_line = static_cast<int>(the_range.size_per_line());
0172 auto start_of_line = the_range.get_begin();
0173 for (auto i = the_range.get_begin(); i != the_range.get_end(); i++)
0174 {
0175 auto ch = static_cast<unsigned char>(*i);
0176
0177 if (put_newlines && (i == the_range.get_begin() || i - start_of_line >= size_per_line))
0178 {
0179 if (show_ascii && i != the_range.get_begin())
0180 {
0181 *inserter++ = delimiter;
0182 *inserter++ = delimiter;
0183 for (auto j = start_of_line; j < i; j++)
0184 {
0185 auto pc = static_cast<unsigned char>(*j);
0186 *inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.';
0187 }
0188 }
0189
0190 put_newline(inserter, static_cast<size_t>(i - the_range.get_begin()));
0191
0192
0193 *inserter++ = hex_chars[(ch >> 4) & 0x0f];
0194 *inserter++ = hex_chars[ch & 0x0f];
0195 start_of_line = i;
0196 continue;
0197 }
0198
0199 if (put_delimiters)
0200 {
0201 *inserter++ = delimiter;
0202 }
0203
0204 *inserter++ = hex_chars[(ch >> 4) & 0x0f];
0205 *inserter++ = hex_chars[ch & 0x0f];
0206 }
0207 if (show_ascii)
0208 {
0209 if (the_range.get_end() - the_range.get_begin() > size_per_line)
0210 {
0211 auto blank_num = size_per_line - (the_range.get_end() - start_of_line);
0212 while (blank_num-- > 0)
0213 {
0214 *inserter++ = delimiter;
0215 *inserter++ = delimiter;
0216 if (put_delimiters)
0217 {
0218 *inserter++ = delimiter;
0219 }
0220 }
0221 }
0222 *inserter++ = delimiter;
0223 *inserter++ = delimiter;
0224 for (auto j = start_of_line; j != the_range.get_end(); j++)
0225 {
0226 auto pc = static_cast<unsigned char>(*j);
0227 *inserter++ = std::isprint(pc) ? static_cast<char>(*j) : '.';
0228 }
0229 }
0230 return inserter;
0231 }
0232
0233
0234 template<typename It>
0235 void put_newline(It inserter, std::size_t pos)
0236 {
0237 #ifdef _WIN32
0238 *inserter++ = '\r';
0239 #endif
0240 *inserter++ = '\n';
0241
0242 if (put_positions)
0243 {
0244 spdlog::fmt_lib::format_to(inserter, SPDLOG_FMT_STRING("{:04X}: "), pos);
0245 }
0246 }
0247 };
0248 }