Add ReadVarInt64Array().

This commit is contained in:
Yury Melnichek 2011-01-09 02:51:44 +02:00 committed by Alex Zolotarev
parent dba3bd8ddf
commit 17815d08b0
2 changed files with 90 additions and 3 deletions

View file

@ -1,8 +1,9 @@
#include "../../base/SRC_FIRST.hpp"
#include "../varint.hpp"
#include "../../testing/testing.hpp"
#include "../byte_stream.hpp"
#include "../varint.hpp"
#include "../../base/macros.hpp"
#include "../../base/stl_add.hpp"
namespace
{
@ -95,3 +96,53 @@ UNIT_TEST(VarIntMax)
TestVarInt(int64_t(9223372036854775807LL));
// TestVarInt(int64_t(-9223372036854775808LL));
}
UNIT_TEST(ReadVarInt64Array_EmptyArray)
{
vector<int64_t> result;
ReadVarInt64Array(NULL, NULL, MakeBackInsertFunctor(result));
TEST_EQUAL(result, vector<int64_t>(), ());
}
UNIT_TEST(ReadVarInt64Array)
{
vector<int64_t> values;
// Fill in values.
{
int64_t const baseValues [] =
{
0, 127, 128, (2 << 28) - 1, (2 << 28), (2 << 31), (2 << 31) - 1,
0xFFFFFFFF - 1, 0xFFFFFFFF, 0xFFFFFFFFFFULL
};
for (size_t i = 0; i < ARRAY_SIZE(baseValues); ++i)
{
values.push_back(baseValues[i]);
values.push_back(-baseValues[i]);
}
sort(values.begin(), values.end());
values.erase(unique(values.begin(), values.end()), values.end());
}
// Test all subsets.
for (size_t i = 1; i < 1 << values.size(); ++i)
{
vector<int64_t> testValues;
for (size_t j = 0; j < values.size(); ++j)
if (i & (1 << j))
testValues.push_back(values[j]);
vector<unsigned char> data;
{
PushBackByteSink<vector<unsigned char> > dst(data);
for (size_t j = 0; j < testValues.size(); ++j)
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, ());
}
}

View file

@ -3,7 +3,7 @@
#include "../base/assert.hpp"
#include "../base/base.hpp"
#include "../base/exception.hpp"
#include "../std/type_traits.hpp"
@ -185,3 +185,39 @@ template <typename T, typename TSource> T ReadVarInt(TSource & src)
STATIC_ASSERT(is_signed<T>::value);
return ZigZagDecode(ReadVarUint<typename make_unsigned<T>::type>(src));
}
DECLARE_EXCEPTION(ReadVarIntException, RootException);
template <typename F> void ReadVarInt64Array(void const * pBeg, void const * pEnd, 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 t = *p;
res32 += (static_cast<uint32_t>(t & 127) << count32);
count32 += 7;
if (!(t & 128))
{
f(ZigZagDecode((static_cast<uint64_t>(res32) << count64) + res64));
res64 = 0;
res32 = 0;
count32 = 0;
count64 = 0;
}
else if (count32 == 28)
{
res64 += (static_cast<uint64_t>(res32) << count64);
res32 = 0;
count32 = 0;
count64 += 28;
}
}
ASSERT(count32 == 0 && res32 == 0 && res64 == 0, (res64, res32, count32));
if (count32 != 0)
MYTHROW(ReadVarIntException, ());
}