forked from OSchip/llvm-project
Added StringExtractor::DecodeHexU8 && GetHexBytesAvail
DecodeHexU8 returns a decoded hex character pair, returns -1 if a valid hex pair is not available. GetHexBytesAvail decodes all available hex pairs. llvm-svn: 223081
This commit is contained in:
parent
e5a9eaaaed
commit
6eddf8df2a
|
@ -21,8 +21,6 @@ TEST_F (StringExtractorTest, InitEmpty)
|
|||
ASSERT_EQ (true, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, InitMisc)
|
||||
|
@ -38,6 +36,79 @@ TEST_F (StringExtractorTest, InitMisc)
|
|||
ASSERT_EQ (kInitMiscString[0], *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, DecodeHexU8_Underflow)
|
||||
{
|
||||
const char kEmptyString[] = "";
|
||||
StringExtractor ex (kEmptyString);
|
||||
|
||||
ASSERT_EQ (-1, ex.DecodeHexU8());
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (0, ex.GetFilePos());
|
||||
ASSERT_EQ (true, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, DecodeHexU8_Underflow2)
|
||||
{
|
||||
const char kEmptyString[] = "1";
|
||||
StringExtractor ex (kEmptyString);
|
||||
|
||||
ASSERT_EQ (-1, ex.DecodeHexU8());
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (0, ex.GetFilePos());
|
||||
ASSERT_EQ (1, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('1', *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, DecodeHexU8_InvalidHex)
|
||||
{
|
||||
const char kInvalidHex[] = "xa";
|
||||
StringExtractor ex (kInvalidHex);
|
||||
|
||||
ASSERT_EQ (-1, ex.DecodeHexU8());
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (0, ex.GetFilePos());
|
||||
ASSERT_EQ (2, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('x', *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, DecodeHexU8_InvalidHex2)
|
||||
{
|
||||
const char kInvalidHex[] = "ax";
|
||||
StringExtractor ex (kInvalidHex);
|
||||
|
||||
ASSERT_EQ (-1, ex.DecodeHexU8());
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (0, ex.GetFilePos());
|
||||
ASSERT_EQ (2, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('a', *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, DecodeHexU8_Exact)
|
||||
{
|
||||
const char kValidHexPair[] = "12";
|
||||
StringExtractor ex (kValidHexPair);
|
||||
|
||||
ASSERT_EQ (0x12, ex.DecodeHexU8());
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (2, ex.GetFilePos());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, DecodeHexU8_Extra)
|
||||
{
|
||||
const char kValidHexPair[] = "1234";
|
||||
StringExtractor ex (kValidHexPair);
|
||||
|
||||
ASSERT_EQ (0x12, ex.DecodeHexU8());
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (2, ex.GetFilePos());
|
||||
ASSERT_EQ (2, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('3', *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, GetHexU8_Underflow)
|
||||
{
|
||||
const char kEmptyString[] = "";
|
||||
|
@ -46,7 +117,6 @@ TEST_F (StringExtractorTest, GetHexU8_Underflow)
|
|||
ASSERT_EQ (0xab, ex.GetHexU8(0xab));
|
||||
ASSERT_EQ (false, ex.IsGood());
|
||||
ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
|
||||
ASSERT_STREQ (kEmptyString, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (true, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
|
@ -60,8 +130,6 @@ TEST_F (StringExtractorTest, GetHexU8_Underflow2)
|
|||
ASSERT_EQ (0xbc, ex.GetHexU8(0xbc));
|
||||
ASSERT_EQ (false, ex.IsGood());
|
||||
ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
|
||||
ASSERT_STREQ (kOneNibble, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
}
|
||||
|
@ -74,8 +142,6 @@ TEST_F (StringExtractorTest, GetHexU8_InvalidHex)
|
|||
ASSERT_EQ (0xcd, ex.GetHexU8(0xcd));
|
||||
ASSERT_EQ (false, ex.IsGood());
|
||||
ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
|
||||
ASSERT_STREQ (kInvalidHex, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
}
|
||||
|
@ -88,8 +154,6 @@ TEST_F (StringExtractorTest, GetHexU8_Exact)
|
|||
ASSERT_EQ (0x12, ex.GetHexU8(0x12));
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (2, ex.GetFilePos());
|
||||
ASSERT_STREQ (kValidHexPair, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
}
|
||||
|
@ -102,8 +166,6 @@ TEST_F (StringExtractorTest, GetHexU8_Extra)
|
|||
ASSERT_EQ (0x12, ex.GetHexU8(0x12));
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (2, ex.GetFilePos());
|
||||
ASSERT_STREQ (kValidHexPair, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (2, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('3', *ex.Peek());
|
||||
}
|
||||
|
@ -117,7 +179,6 @@ TEST_F (StringExtractorTest, GetHexU8_Underflow_NoEof)
|
|||
ASSERT_EQ (0xab, ex.GetHexU8(0xab, kSetEofOnFail));
|
||||
ASSERT_EQ (false, ex.IsGood()); // this result seems inconsistent with kSetEofOnFail == false
|
||||
ASSERT_EQ (UINT64_MAX, ex.GetFilePos());
|
||||
ASSERT_STREQ (kEmptyString, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (true, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
|
@ -132,8 +193,6 @@ TEST_F (StringExtractorTest, GetHexU8_Underflow2_NoEof)
|
|||
ASSERT_EQ (0xbc, ex.GetHexU8(0xbc, kSetEofOnFail));
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (0, ex.GetFilePos());
|
||||
ASSERT_STREQ (kOneNibble, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (1, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('1', *ex.Peek());
|
||||
}
|
||||
|
@ -147,8 +206,6 @@ TEST_F (StringExtractorTest, GetHexU8_InvalidHex_NoEof)
|
|||
ASSERT_EQ (0xcd, ex.GetHexU8(0xcd, kSetEofOnFail));
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (0, ex.GetFilePos());
|
||||
ASSERT_STREQ (kInvalidHex, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (2, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('x', *ex.Peek());
|
||||
}
|
||||
|
@ -162,8 +219,6 @@ TEST_F (StringExtractorTest, GetHexU8_Exact_NoEof)
|
|||
ASSERT_EQ (0x12, ex.GetHexU8(0x12, kSetEofOnFail));
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (2, ex.GetFilePos());
|
||||
ASSERT_STREQ (kValidHexPair, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (0, ex.GetBytesLeft());
|
||||
ASSERT_EQ (nullptr, ex.Peek());
|
||||
}
|
||||
|
@ -177,8 +232,6 @@ TEST_F (StringExtractorTest, GetHexU8_Extra_NoEof)
|
|||
ASSERT_EQ (0x12, ex.GetHexU8(0x12, kSetEofOnFail));
|
||||
ASSERT_EQ (true, ex.IsGood());
|
||||
ASSERT_EQ (2, ex.GetFilePos());
|
||||
ASSERT_STREQ (kValidHexPair, ex.GetStringRef().c_str());
|
||||
ASSERT_EQ (false, ex.Empty());
|
||||
ASSERT_EQ (2, ex.GetBytesLeft());
|
||||
ASSERT_EQ ('3', *ex.Peek());
|
||||
}
|
||||
|
@ -265,3 +318,89 @@ TEST_F (StringExtractorTest, GetHexBytes_Partial)
|
|||
ASSERT_EQ(12, ex.GetBytesLeft());
|
||||
ASSERT_EQ('2', *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, GetHexBytesAvail)
|
||||
{
|
||||
const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
|
||||
const size_t kValidHexPairs = 8;
|
||||
StringExtractor ex(kHexEncodedBytes);
|
||||
|
||||
uint8_t dst[kValidHexPairs];
|
||||
ASSERT_EQ(kValidHexPairs, ex.GetHexBytesAvail (dst, kValidHexPairs));
|
||||
EXPECT_EQ(0xab,dst[0]);
|
||||
EXPECT_EQ(0xcd,dst[1]);
|
||||
EXPECT_EQ(0xef,dst[2]);
|
||||
EXPECT_EQ(0x01,dst[3]);
|
||||
EXPECT_EQ(0x23,dst[4]);
|
||||
EXPECT_EQ(0x45,dst[5]);
|
||||
EXPECT_EQ(0x67,dst[6]);
|
||||
EXPECT_EQ(0x89,dst[7]);
|
||||
|
||||
ASSERT_EQ(true, ex.IsGood());
|
||||
ASSERT_EQ(2*kValidHexPairs, ex.GetFilePos());
|
||||
ASSERT_EQ(false, ex.Empty());
|
||||
ASSERT_EQ(4, ex.GetBytesLeft());
|
||||
ASSERT_EQ('x', *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, GetHexBytesAvail_Underflow)
|
||||
{
|
||||
const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
|
||||
const size_t kValidHexPairs = 8;
|
||||
StringExtractor ex(kHexEncodedBytes);
|
||||
|
||||
uint8_t dst[12];
|
||||
memset(dst, 0xef, sizeof(dst));
|
||||
ASSERT_EQ(kValidHexPairs, ex.GetHexBytesAvail (dst, sizeof(dst)));
|
||||
EXPECT_EQ(0xab,dst[0]);
|
||||
EXPECT_EQ(0xcd,dst[1]);
|
||||
EXPECT_EQ(0xef,dst[2]);
|
||||
EXPECT_EQ(0x01,dst[3]);
|
||||
EXPECT_EQ(0x23,dst[4]);
|
||||
EXPECT_EQ(0x45,dst[5]);
|
||||
EXPECT_EQ(0x67,dst[6]);
|
||||
EXPECT_EQ(0x89,dst[7]);
|
||||
// these bytes should be unchanged
|
||||
EXPECT_EQ(0xef,dst[8]);
|
||||
EXPECT_EQ(0xef,dst[9]);
|
||||
EXPECT_EQ(0xef,dst[10]);
|
||||
EXPECT_EQ(0xef,dst[11]);
|
||||
|
||||
ASSERT_EQ(true, ex.IsGood());
|
||||
ASSERT_EQ(kValidHexPairs*2, ex.GetFilePos());
|
||||
ASSERT_EQ(false, ex.Empty());
|
||||
ASSERT_EQ(4, ex.GetBytesLeft());
|
||||
ASSERT_EQ('x', *ex.Peek());
|
||||
}
|
||||
|
||||
TEST_F (StringExtractorTest, GetHexBytesAvail_Partial)
|
||||
{
|
||||
const char kHexEncodedBytes[] = "abcdef0123456789xyzw";
|
||||
const size_t kReadBytes = 4;
|
||||
StringExtractor ex(kHexEncodedBytes);
|
||||
|
||||
uint8_t dst[12];
|
||||
memset(dst, 0xab, sizeof(dst));
|
||||
ASSERT_EQ(kReadBytes, ex.GetHexBytesAvail (dst, kReadBytes));
|
||||
EXPECT_EQ(0xab,dst[0]);
|
||||
EXPECT_EQ(0xcd,dst[1]);
|
||||
EXPECT_EQ(0xef,dst[2]);
|
||||
EXPECT_EQ(0x01,dst[3]);
|
||||
// these bytes should be unchanged
|
||||
EXPECT_EQ(0xab,dst[4]);
|
||||
EXPECT_EQ(0xab,dst[5]);
|
||||
EXPECT_EQ(0xab,dst[6]);
|
||||
EXPECT_EQ(0xab,dst[7]);
|
||||
EXPECT_EQ(0xab,dst[8]);
|
||||
EXPECT_EQ(0xab,dst[9]);
|
||||
EXPECT_EQ(0xab,dst[10]);
|
||||
EXPECT_EQ(0xab,dst[11]);
|
||||
|
||||
ASSERT_EQ(true, ex.IsGood());
|
||||
ASSERT_EQ(kReadBytes*2, ex.GetFilePos());
|
||||
ASSERT_EQ(false, ex.Empty());
|
||||
ASSERT_EQ(12, ex.GetBytesLeft());
|
||||
ASSERT_EQ('2', *ex.Peek());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,43 +16,6 @@
|
|||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
|
||||
static const uint8_t
|
||||
g_hex_ascii_to_hex_integer[256] = {
|
||||
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
|
||||
0x8, 0x9, 255, 255, 255, 255, 255, 255,
|
||||
255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
};
|
||||
|
||||
static inline int
|
||||
xdigit_to_sint (char ch)
|
||||
{
|
||||
|
@ -60,7 +23,9 @@ xdigit_to_sint (char ch)
|
|||
return 10 + ch - 'a';
|
||||
if (ch >= 'A' && ch <= 'F')
|
||||
return 10 + ch - 'A';
|
||||
return ch - '0';
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
return -1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -128,6 +93,31 @@ StringExtractor::GetChar (char fail_value)
|
|||
return fail_value;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// If a pair of valid hex digits exist at the head of the
|
||||
// StringExtractor they are decoded into an unsigned byte and returned
|
||||
// by this function
|
||||
//
|
||||
// If there is not a pair of valid hex digits at the head of the
|
||||
// StringExtractor, it is left unchanged and -1 is returned
|
||||
//----------------------------------------------------------------------
|
||||
int
|
||||
StringExtractor::DecodeHexU8()
|
||||
{
|
||||
if (GetBytesLeft() < 2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
const int hi_nibble = xdigit_to_sint(m_packet[m_index]);
|
||||
const int lo_nibble = xdigit_to_sint(m_packet[m_index+1]);
|
||||
if (hi_nibble == -1 || lo_nibble == -1)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
m_index += 2;
|
||||
return (uint8_t)((hi_nibble << 4) + lo_nibble);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Extract an unsigned character from two hex ASCII chars in the packet
|
||||
// string
|
||||
|
@ -135,19 +125,14 @@ StringExtractor::GetChar (char fail_value)
|
|||
uint8_t
|
||||
StringExtractor::GetHexU8 (uint8_t fail_value, bool set_eof_on_fail)
|
||||
{
|
||||
if (GetBytesLeft() >= 2)
|
||||
int byte = DecodeHexU8();
|
||||
if (byte == -1)
|
||||
{
|
||||
const uint8_t hi_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index])];
|
||||
const uint8_t lo_nibble = g_hex_ascii_to_hex_integer[static_cast<uint8_t>(m_packet[m_index+1])];
|
||||
if (hi_nibble < 16 && lo_nibble < 16)
|
||||
{
|
||||
m_index += 2;
|
||||
return (hi_nibble << 4) + lo_nibble;
|
||||
}
|
||||
if (set_eof_on_fail || m_index >= m_packet.size())
|
||||
m_index = UINT64_MAX;
|
||||
return fail_value;
|
||||
}
|
||||
if (set_eof_on_fail || m_index >= m_packet.size())
|
||||
m_index = UINT64_MAX;
|
||||
return fail_value;
|
||||
return (uint8_t)byte;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -372,6 +357,28 @@ StringExtractor::GetHexBytes (void *dst_void, size_t dst_len, uint8_t fail_fill_
|
|||
return bytes_extracted;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Decodes all valid hex encoded bytes at the head of the
|
||||
// StringExtractor, limited by dst_len.
|
||||
//
|
||||
// Returns the number of bytes successfully decoded
|
||||
//----------------------------------------------------------------------
|
||||
size_t
|
||||
StringExtractor::GetHexBytesAvail (void *dst_void, size_t dst_len)
|
||||
{
|
||||
uint8_t *dst = (uint8_t*)dst_void;
|
||||
size_t bytes_extracted = 0;
|
||||
while (bytes_extracted < dst_len)
|
||||
{
|
||||
int decode = DecodeHexU8();
|
||||
if (decode == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
dst[bytes_extracted++] = (uint8_t)decode;
|
||||
}
|
||||
return bytes_extracted;
|
||||
}
|
||||
|
||||
// Consume ASCII hex nibble character pairs until we have decoded byte_size
|
||||
// bytes of data.
|
||||
|
|
|
@ -92,9 +92,13 @@ public:
|
|||
return m_packet.size() - m_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char
|
||||
GetChar (char fail_value = '\0');
|
||||
|
||||
int
|
||||
DecodeHexU8();
|
||||
|
||||
uint8_t
|
||||
GetHexU8 (uint8_t fail_value = 0, bool set_eof_on_fail = true);
|
||||
|
||||
|
@ -122,6 +126,9 @@ public:
|
|||
size_t
|
||||
GetHexBytes (void *dst, size_t dst_len, uint8_t fail_fill_value);
|
||||
|
||||
size_t
|
||||
GetHexBytesAvail (void *dst, size_t dst_len);
|
||||
|
||||
uint64_t
|
||||
GetHexWithFixedSize (uint32_t byte_size, bool little_endian, uint64_t fail_value);
|
||||
|
||||
|
|
Loading…
Reference in New Issue