Merge pull request #7786 from ethereum/fixHexCase

Fix hex case
This commit is contained in:
chriseth 2019-11-26 11:55:54 +01:00 committed by GitHub
commit 200a92b40e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 25 deletions

View File

@ -29,26 +29,52 @@
using namespace std; using namespace std;
using namespace dev; using namespace dev;
namespace
{
static char const* upperHexChars = "0123456789ABCDEF";
static char const* lowerHexChars = "0123456789abcdef";
}
string dev::toHex(uint8_t _data, HexCase _case)
{
assertThrow(_case != HexCase::Mixed, BadHexCase, "Mixed case can only be used for byte arrays.");
char const* chars = _case == HexCase::Upper ? upperHexChars : lowerHexChars;
return std::string{
chars[(unsigned(_data) / 16) & 0xf],
chars[unsigned(_data) & 0xf]
};
}
string dev::toHex(bytes const& _data, HexPrefix _prefix, HexCase _case) string dev::toHex(bytes const& _data, HexPrefix _prefix, HexCase _case)
{ {
std::ostringstream ret; std::string ret(_data.size() * 2 + (_prefix == HexPrefix::Add ? 2 : 0), 0);
if (_prefix == HexPrefix::Add)
ret << "0x";
size_t i = 0;
if (_prefix == HexPrefix::Add)
{
ret[i++] = '0';
ret[i++] = 'x';
}
// Mixed case will be handled inside the loop.
char const* chars = _case == HexCase::Upper ? upperHexChars : lowerHexChars;
int rix = _data.size() - 1; int rix = _data.size() - 1;
for (uint8_t c: _data) for (uint8_t c: _data)
{ {
// switch hex case every four hexchars // switch hex case every four hexchars
auto hexcase = std::nouppercase; if (_case == HexCase::Mixed)
if (_case == HexCase::Upper) chars = (rix-- & 2) == 0 ? lowerHexChars : upperHexChars;
hexcase = std::uppercase;
else if (_case == HexCase::Mixed)
hexcase = (rix-- & 2) == 0 ? std::nouppercase : std::uppercase;
ret << std::hex << hexcase << std::setfill('0') << std::setw(2) << size_t(c); ret[i++] = chars[(unsigned(c) / 16) & 0xf];
ret[i++] = chars[unsigned(c) & 0xf];
} }
assertThrow(i == ret.size(), Exception, "");
return ret.str(); return ret;
} }
int dev::fromHex(char _i, WhenError _throw) int dev::fromHex(char _i, WhenError _throw)

View File

@ -130,9 +130,12 @@ enum class HexCase
Mixed = 2, Mixed = 2,
}; };
/// Convert a series of bytes to the corresponding string of hex duplets. /// Convert a single byte to a string of hex characters (of length two),
/// @param _w specifies the width of the first of the elements. Defaults to two - enough to represent a byte. /// optionally with uppercase hex letters.
/// @example toHex("A\x69") == "4169" std::string toHex(uint8_t _data, HexCase _case = HexCase::Lower);
/// Convert a series of bytes to the corresponding string of hex duplets,
/// optionally with "0x" prefix and with uppercase hex letters.
std::string toHex(bytes const& _data, HexPrefix _prefix = HexPrefix::DontAdd, HexCase _case = HexCase::Lower); std::string toHex(bytes const& _data, HexPrefix _prefix = HexPrefix::DontAdd, HexCase _case = HexCase::Lower);
/// Converts a (printable) ASCII hex character into the corresponding integer value. /// Converts a (printable) ASCII hex character into the corresponding integer value.
@ -207,10 +210,6 @@ inline bytes toCompactBigEndian(T _val, unsigned _min = 0)
toBigEndian(_val, ret); toBigEndian(_val, ret);
return ret; return ret;
} }
inline bytes toCompactBigEndian(uint8_t _val, unsigned _min = 0)
{
return (_min || _val) ? bytes{ _val } : bytes{};
}
/// Convenience function for conversion of a u256 to hex /// Convenience function for conversion of a u256 to hex
inline std::string toHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd) inline std::string toHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd)
@ -219,13 +218,18 @@ inline std::string toHex(u256 val, HexPrefix prefix = HexPrefix::DontAdd)
return (prefix == HexPrefix::Add) ? "0x" + str : str; return (prefix == HexPrefix::Add) ? "0x" + str : str;
} }
inline std::string toCompactHexWithPrefix(u256 const& _value)
{
return toHex(toCompactBigEndian(_value, 1), HexPrefix::Add);
}
/// Returns decimal representation for small numbers and hex for large numbers. /// Returns decimal representation for small numbers and hex for large numbers.
inline std::string formatNumber(bigint const& _value) inline std::string formatNumber(bigint const& _value)
{ {
if (_value < 0) if (_value < 0)
return "-" + formatNumber(-_value); return "-" + formatNumber(-_value);
if (_value > 0x1000000) if (_value > 0x1000000)
return toHex(toCompactBigEndian(_value), HexPrefix::Add); return toHex(toCompactBigEndian(_value, 1), HexPrefix::Add);
else else
return _value.str(); return _value.str();
} }
@ -233,17 +237,11 @@ inline std::string formatNumber(bigint const& _value)
inline std::string formatNumber(u256 const& _value) inline std::string formatNumber(u256 const& _value)
{ {
if (_value > 0x1000000) if (_value > 0x1000000)
return toHex(toCompactBigEndian(_value), HexPrefix::Add); return toCompactHexWithPrefix(_value);
else else
return _value.str(); return _value.str();
} }
inline std::string toCompactHexWithPrefix(u256 val)
{
std::ostringstream ret;
ret << std::hex << val;
return "0x" + ret.str();
}
// Algorithms for string and string-like collections. // Algorithms for string and string-like collections.

View File

@ -46,6 +46,7 @@ private:
DEV_SIMPLE_EXCEPTION(InvalidAddress); DEV_SIMPLE_EXCEPTION(InvalidAddress);
DEV_SIMPLE_EXCEPTION(BadHexCharacter); DEV_SIMPLE_EXCEPTION(BadHexCharacter);
DEV_SIMPLE_EXCEPTION(BadHexCase);
DEV_SIMPLE_EXCEPTION(FileError); DEV_SIMPLE_EXCEPTION(FileError);
DEV_SIMPLE_EXCEPTION(DataTooLong); DEV_SIMPLE_EXCEPTION(DataTooLong);