Potrzebuję zaimplementować funkcję dekodującą LEB128 ze znakiem.
Implementacje opracowałem dosłownie na podstawie opisu "Decode signed integer" z https://en.wikipedia.org/wiki/LEB128
typedef unsigned char uchar;
typedef signed long long sllong;
// raw - tabloca bajtowa
// ptr - pierwszy bajt dekodowanej liczby
// size - wielkość liczby - zazwyczaj 32 lub 64
// leb128Size - liczba bajtów liczby w tablicy, obliczona po zdekodowaniu
sllong fileStructure::leb128s(uchar * raw, int ptr, int size, int &leb128Size)
{
sllong result = 0;
int shift = 0;
leb128Size = 0;
do
{
// 8080808010370210 64 - runtime error: left shift of 16 by 28 places cannot be represented in type 'int'
// 8080808080808080807F 64 - runtime error: shift exponent 35 is too large for 32-bit type 'int'
// FFFFFFFFFFFFFFEF3F84 64 - runtime error: left shift of 127 by 28 places cannot be represented in type 'int'
result |= (((int)raw[ptr] & 0b01111111) << shift);
shift += 7;
ptr++;
leb128Size++;
}
while ((raw[ptr - 1] & 0b10000000));
if ((shift < size) && (raw[ptr - 1] & 0b01000000))
{
// 7C712105 32 - runtime error: left shift of negative value -1
// 7C712108 32
// 7C712202 32
// 7C712204 32
// 7C712205 32
// 7C712207 32
// 7C71220A 32
// 7F10E616 32
// 7F10EE16 32
// 7F10EF16 32
// 70712202 32
// 70716B22 32
// 406A2202 32
// 406B2400 32
// 7E712107 32
result |= (~0 << shift);
}
return result;
}
Po zaimplementowaniu według opisu z Wikipedii i sprawdzeniu kilku przypadków funkcja wydawała się działać, ale po właczeniu sanitizerów i próbie odczytu większego pliku, gdzie jest bardzo dużo liczb, dostawałem komunikaty błędów.
Informacje wklepiłem jako komentarze wraz z przypadkami testowymi. Każdy przypadek testowy, to ciąg bajtów w hex (na przykład 7C71220A znaczy ciąg 0x7c, 0x71, 0x22, 0x0A) w tablicy poczynając od ptr i wielkośc podstawiona za size. Ciąg bajtów będący przypadkiem testowym może być dłuższy niż faktycznie zawierający liczbę LEB128.
- Co potrzeba w tej funkcji poprawić, żeby nie zmienił działania dla poprawnych przypadków (czyli 99% przypadków użytku tej funkcji, które nie są wyżej wymienione), niezależnie od podanej wielkości
size? - Czy jest w internecie działający kalkulator LEB128 ze znakiem, gdzie mogę sprawdzić trudniejsze przypadki, czy mój kod daje poprawny wynik?