ReadVarInt64() for an array of a given size.

This commit is contained in:
Yury Melnichek 2011-01-12 23:47:54 +02:00 committed by Alex Zolotarev
parent 05450b06ed
commit dc3802b910
2 changed files with 69 additions and 9 deletions

View file

@ -100,8 +100,12 @@ UNIT_TEST(VarIntMax)
UNIT_TEST(ReadVarInt64Array_EmptyArray)
{
vector<int64_t> result;
ReadVarInt64Array(NULL, NULL, MakeBackInsertFunctor(result));
TEST_EQUAL(result, vector<int64_t>(), ());
void const * pEnd = ReadVarInt64Array(NULL, (void *)0, MakeBackInsertFunctor(result));
TEST_EQUAL(result, vector<int64_t>(), ("UntilBufferEnd"));
TEST_EQUAL(reinterpret_cast<uintptr_t>(pEnd), 0, ("UntilBufferEnd"));
pEnd = ReadVarInt64Array(NULL, (size_t)0, MakeBackInsertFunctor(result));
TEST_EQUAL(result, vector<int64_t>(), ("GivenSize"));
TEST_EQUAL(reinterpret_cast<uintptr_t>(pEnd), 0, ("GivenSize"));
}
UNIT_TEST(ReadVarInt64Array)
@ -139,10 +143,21 @@ UNIT_TEST(ReadVarInt64Array)
WriteVarInt(dst, testValues[j]);
}
vector<int64_t> result;
ASSERT_GREATER(data.size(), 0, ());
ReadVarInt64Array(&data[0], &data[0] + data.size(), MakeBackInsertFunctor(result));
TEST_EQUAL(result, testValues, ());
{
vector<int64_t> result;
void const * pEnd = ReadVarInt64Array(&data[0], &data[0] + data.size(),
MakeBackInsertFunctor(result));
TEST_EQUAL(pEnd, &data[0] + data.size(), ("UntilBufferEnd", data.size()));
TEST_EQUAL(result, testValues, ("UntilBufferEnd", data.size()));
}
{
vector<int64_t> result;
void const * pEnd = ReadVarInt64Array(&data[0], testValues.size(),
MakeBackInsertFunctor(result));
TEST_EQUAL(pEnd, &data[0] + data.size(), ("GivenSize", data.size()));
TEST_EQUAL(result, testValues, ("GivenSize", data.size()));
}
}
}

View file

@ -188,22 +188,51 @@ template <typename T, typename TSource> T ReadVarInt(TSource & src)
DECLARE_EXCEPTION(ReadVarIntException, RootException);
template <typename F> void ReadVarInt64Array(void const * pBeg, void const * pEnd, F f)
namespace impl
{
class ReadVarInt64ArrayUntilBufferEnd
{
public:
explicit ReadVarInt64ArrayUntilBufferEnd(void const * pEnd) : m_pEnd(pEnd) {}
bool Continue(void const * p) const
{
ASSERT_LESS_OR_EQUAL(reinterpret_cast<uintptr_t>(p), reinterpret_cast<uintptr_t>(m_pEnd), ());
return p < m_pEnd;
}
void NextVarInt() {}
private:
void const * m_pEnd;
};
class ReadVarInt64ArrayGivenSize
{
public:
explicit ReadVarInt64ArrayGivenSize(size_t const count) : m_Remaining(count) {}
bool Continue(void const *) const { return m_Remaining > 0; }
void NextVarInt() { --m_Remaining; }
private:
size_t m_Remaining;
};
template <typename F, class WhileConditionT>
void const * ReadVarInt64Array(void const * pBeg, WhileConditionT whileCondition, F f)
{
uint8_t const * const pBegChar = static_cast<uint8_t const *>(pBeg);
uint8_t const * const pEndChar = static_cast<uint8_t const *>(pEnd);
uint64_t res64 = 0;
uint32_t res32 = 0;
uint32_t count32 = 0;
uint32_t count64 = 0;
for (uint8_t const * p = pBegChar; p < pEndChar; ++p)
uint8_t const * p = pBegChar;
while (whileCondition.Continue(p))
{
uint8_t const t = *p;
uint8_t const t = *p++;
res32 += (static_cast<uint32_t>(t & 127) << count32);
count32 += 7;
if (!(t & 128))
{
f(ZigZagDecode((static_cast<uint64_t>(res32) << count64) + res64));
whileCondition.NextVarInt();
res64 = 0;
res32 = 0;
count32 = 0;
@ -220,4 +249,20 @@ template <typename F> void ReadVarInt64Array(void const * pBeg, void const * pEn
ASSERT(count32 == 0 && res32 == 0 && res64 == 0, (res64, res32, count32));
if (count32 != 0)
MYTHROW(ReadVarIntException, ());
return p;
}
}
template <typename F> inline
void const * ReadVarInt64Array(void const * pBeg, void const * pEnd, F f)
{
return impl::ReadVarInt64Array(pBeg, impl::ReadVarInt64ArrayUntilBufferEnd(pEnd), f);
}
template <typename F> inline
void const * ReadVarInt64Array(void const * pBeg, size_t count, F f)
{
return impl::ReadVarInt64Array(pBeg, impl::ReadVarInt64ArrayGivenSize(count), f);
}