git-subtree-dir: xo-indentlog git-subtree-mainline:1c3f033933git-subtree-split:d43c4af0b4
145 lines
4.3 KiB
C++
145 lines
4.3 KiB
C++
/** @file hex.hpp **/
|
|
|
|
#pragma once
|
|
|
|
#include <iostream>
|
|
#include <cstdint>
|
|
|
|
namespace xo {
|
|
/**
|
|
@class hex indentlog/print/hex.hpp
|
|
|
|
@brief Container for a (1-byte) value to be printed in hexadecimal
|
|
|
|
Example:
|
|
@code
|
|
#include "indentlog/print/hex.hpp"
|
|
|
|
std::ostream os = ...;
|
|
os << hex(16 + 63); // output: 1f
|
|
os << hex(16 + 63, true); // output: 1f(O)
|
|
@endcode
|
|
**/
|
|
struct hex {
|
|
/** @brief constructor; create stream-inserter instance */
|
|
explicit hex(std::uint8_t x, bool w_char = false) : x_{x}, with_char_{w_char} {}
|
|
|
|
/**
|
|
@brief print hexadecimal byte-value on to stream.
|
|
@param os print on this stream.
|
|
|
|
@tparam Stream typename for character stream.
|
|
**/
|
|
template <typename Stream>
|
|
void print(Stream & os) const {
|
|
std::uint8_t lo = x_ & 0xf;
|
|
std::uint8_t hi = x_ >> 4;
|
|
|
|
char lo_ch = (lo < 10) ? '0' + lo : 'a' + lo - 10;
|
|
char hi_ch = (hi < 10) ? '0' + hi : 'a' + hi - 10;
|
|
|
|
os << hi_ch << lo_ch;
|
|
|
|
if (with_char_) {
|
|
os << "(";
|
|
if (std::isprint(x_))
|
|
os << static_cast<char>(x_);
|
|
else
|
|
os << "?";
|
|
os << ")";
|
|
}
|
|
}
|
|
|
|
private:
|
|
/** @brief value to print (in hexadecimal) **/
|
|
std::uint8_t x_;
|
|
/** @brief if true, follow with ascii character encoding **/
|
|
bool with_char_;
|
|
};
|
|
|
|
/**
|
|
@brief stream inserter for an 8-bit quantity to be printed in hexadecimal.
|
|
|
|
@param os print on this stream
|
|
@param ins package for value to insert
|
|
**/
|
|
inline std::iostream &
|
|
operator<< (std::iostream & os, hex const & ins) {
|
|
ins.print(os);
|
|
return os;
|
|
}
|
|
|
|
/**
|
|
@class hex_view indentlog/print/hex.hpp
|
|
|
|
@brief Container for a range (unowned) of 1-byte values to be printed in hexadecimal
|
|
|
|
Print a range of bytes on an arbitrary character stream.
|
|
Does not use @c iomanips, so will not alter stream formatting flags if used with @c iostream.
|
|
|
|
Example:
|
|
@code
|
|
#include "indentlog/print/hex.hpp"
|
|
|
|
std::ostream os = ...;
|
|
os << hex_view("hello", false); // output: [68 65 6c 6c 6f]
|
|
os << hex_view("hello", true); // output: [68(h) 65(e) 6c(l) 6c(l) 6f(o)]
|
|
@endcode
|
|
**/
|
|
struct hex_view {
|
|
/** @brief constructor; create stream-inserter instance for a range of bytes **/
|
|
hex_view(std::uint8_t const * lo, std::uint8_t const * hi, bool as_text)
|
|
: lo_{lo}, hi_{hi}, as_text_{as_text} {}
|
|
/** @brief constructor; create stream-inserter instance for a range of chars **/
|
|
hex_view(char const * lo, char const * hi, bool as_text)
|
|
: lo_{reinterpret_cast<std::uint8_t const *>(lo)},
|
|
hi_{reinterpret_cast<std::uint8_t const *>(hi)},
|
|
as_text_{as_text} {}
|
|
|
|
/**
|
|
@brief print hexadecimal byte range on stream.
|
|
@param os print on this stream
|
|
|
|
@tparam Stream typename for character stream.
|
|
**/
|
|
template <typename Stream>
|
|
void print(Stream & os) const {
|
|
os << "[";
|
|
std::size_t i = 0;
|
|
for (std::uint8_t const * p = lo_; p < hi_; ++p) {
|
|
if (i > 0)
|
|
os << " ";
|
|
xo::hex(*p, as_text_).print(os);
|
|
//os << xo::hex(*p, as_text_);
|
|
++i;
|
|
}
|
|
os << "]";
|
|
}
|
|
|
|
private:
|
|
/** @brief print byte range starting at this address **/
|
|
std::uint8_t const * lo_;
|
|
/** @brief print byte range up to (but not including) this address **/
|
|
std::uint8_t const * hi_;
|
|
/** @brief if true also print ascii encoding (for printable codes),
|
|
* \c ? otherwise. @see hex::with_char
|
|
**/
|
|
bool as_text_;
|
|
};
|
|
|
|
/**
|
|
@brief stream inserter for a range of 1-byte values to be printed in hexadecimal
|
|
|
|
@param os print on this stream.
|
|
@param ins (container for) values to insert.
|
|
**/
|
|
template <typename Stream>
|
|
Stream &
|
|
operator<< (Stream & os, hex_view const & ins) {
|
|
ins.print(os);
|
|
return os;
|
|
}
|
|
|
|
} /*namespace xo*/
|
|
|
|
/* end hex.hpp */
|