Hex.h

// Hex.h
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2008

#pragma once
#ifndef Ceda_cxUtils_Hex_H
#define Ceda_cxUtils_Hex_H

#include "cxUtils.h"
#include "Archive.h"
#include "xstring.h"

namespace ceda
{
class xostream;

cxUtils_API bool IsHexDigit(xchar c);
cxUtils_API int MapHexDigit(xchar c);
cxUtils_API int32 StringToHexInt(const xstring& str);

///////////////////////////////////////////////////////////////////////////////////////////////////

cxUtils_API void HexDump(
    xostream& os, ssize_t numPerLine, bool showAscii, const octet_t* r1, const octet_t* r2);

/*
Example

    0x12,0xFF,0x01,0x60,
    0x27,0x45
*/
cxUtils_API void WriteByteArrayInHex(xostream& os, ssize_t numPerLine, xchar delimiter, const octet_t* A, ssize_t n);

///////////////////////////////////////////////////////////////////////////////////////////////////
// Convenient wrapper for writing hex numbers to a stream
//
// Example
//              int x = 0x102;
//              os << AsHex(x);

template <typename T>
struct HexNumber
{
    HexNumber(T _x = 0) : x(_x) {}
    operator T() const { return x; }
    T x;
};

template <typename T>
HexNumber<T> AsHex(T x) { return HexNumber<T>(x); }

/*
Write the value of size 'numBytes' starting at address 'buffer' as a hex number to xostream 
'os'. If 'uppercase' is true then uppercase hex digits A,B,C,D,E,F are used (else lowercase)
E.g. a 16 bit value would have numBytes = 2, and a 4 digit hex number such as 000a is 
written.  The order of the digits depends on whether the machine is little or big endian.
[Currently little endian is assumed, so the right most pair of hex digits corresponds to the
byte at the lowest address (i.e. at 'buffer').
*/
cxUtils_API void WriteHex(xostream& os, const void* buffer, ssize_t numBytes, bool uppercase = false);

template <typename T>
inline xostream& operator<<(xostream& os, HexNumber<T> i)
{
    WriteHex(os, &i.x, sizeof(T));
    return os;
}

template <typename Archive, typename T> 
inline void Serialise(Archive& ar, const HexNumber<T>& x)
{
    ar.SerialisePod(x);
}

template <typename Archive, typename T> 
inline void Deserialise(Archive& ar, HexNumber<T>& x)
{
    ar.DeserialisePod(x);
}

} // namespace ceda

#endif // include guard