İlk kapalı, varyasyonların gerçek bayt olarak gönderildiğini, 1
ve 0
karakterlerinin dizelerini değil.
İmzasız bir varyant için, data
ile işaretlenmiş bir arabellekte varyant verilerini aldığınızı varsayarak, aşağıdakilerin sizin için şifresini çözeceğine inanıyorum. Bu örnek işlevi, int decoded_bytes
referans argümanında çözülen bayt sayısını döndürür.
uint64_t decode_unsigned_varint(const uint8_t *const data, int &decoded_bytes)
{
int i = 0;
uint64_t decoded_value = 0;
int shift_amount = 0;
do
{
decoded_value |= (uint64_t)(data[i] & 0x7F) << shift_amount;
shift_amount += 7;
} while ((data[i++] & 0x80) != 0);
decoded_bytes = i;
return decoded_value;
}
imzalı VARINT deşifre etmek için önce çağıran bu ikinci işlevi kullanabilirsiniz:
int64_t decode_signed_varint(const uint8_t *const data, int &decoded_bytes)
{
uint64_t unsigned_value = decode_unsigned_varint(data, decoded_bytes);
return (int64_t)(unsigned_value & 1 ? ~(unsigned_value >> 1)
: (unsigned_value >> 1));
}
Ben bu fonksiyonların her ikisi doğru olduğuna inanıyoruz. Google sayfasından birkaç veri noktasını doğrulamak için aşağıdaki kodla bazı temel testler yaptım. Çıkış doğru.
#include <stdint.h>
#include <iostream>
uint64_t decode_unsigned_varint(const uint8_t *const data, int &decoded_bytes)
{
int i = 0;
uint64_t decoded_value = 0;
int shift_amount = 0;
do
{
decoded_value |= (uint64_t)(data[i] & 0x7F) << shift_amount;
shift_amount += 7;
} while ((data[i++] & 0x80) != 0);
decoded_bytes = i;
return decoded_value;
}
int64_t decode_signed_varint(const uint8_t *const data, int &decoded_bytes)
{
uint64_t unsigned_value = decode_unsigned_varint(data, decoded_bytes);
return (int64_t)(unsigned_value & 1 ? ~(unsigned_value >> 1)
: (unsigned_value >> 1));
}
uint8_t ex_p300[] = { 0xAC, 0x02 };
uint8_t ex_n1 [] = { 0x01 };
using namespace std;
int main()
{
int decoded_bytes_p300;
uint64_t p300;
p300 = decode_unsigned_varint(ex_p300, decoded_bytes_p300);
int decoded_bytes_n1;
int64_t n1;
n1 = decode_signed_varint(ex_n1, decoded_bytes_n1);
cout << "p300 = " << p300
<< " decoded_bytes_p300 = " << decoded_bytes_p300 << endl;
cout << "n1 = " << n1
<< " decoded_bytes_n1 = " << decoded_bytes_n1 << endl;
return 0;
}
Değişiklikleri kodlamak için aşağıdaki işlevleri kullanabilirsiniz. büyük VarInt 10 bayt uzunluğunda olduğu gibi tampon uint8_t *const data
, en az 10 baytlık bir yere sahip olduğunu unutmayın.
#include hiç görmedim
// Encode an unsigned 64-bit varint. Returns number of encoded bytes.
// 'buffer' must have room for up to 10 bytes.
int encode_unsigned_varint(uint8_t *const buffer, uint64_t value)
{
int encoded = 0;
do
{
uint8_t next_byte = value & 0x7F;
value >>= 7;
if (value)
next_byte |= 0x80;
buffer[encoded++] = next_byte;
} while (value);
return encoded;
}
// Encode a signed 64-bit varint. Works by first zig-zag transforming
// signed value into an unsigned value, and then reusing the unsigned
// encoder. 'buffer' must have room for up to 10 bytes.
int encode_signed_varint(uint8_t *const buffer, int64_t value)
{
uint64_t uvalue;
uvalue = uint64_t(value < 0 ? ~(value << 1) : (value << 1));
return encode_unsigned_varint(buffer, uvalue);
}
önce varints ama "VarInt c kütüphanesinde" için google çalıştı ve birkaç darbe aldık. Bu büyük cevap için –