forked from organicmaps/organicmaps
Add ReadVarInt64Array().
This commit is contained in:
parent
dba3bd8ddf
commit
17815d08b0
2 changed files with 90 additions and 3 deletions
|
@ -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, ());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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, ());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue