Je lis la spécification du format avro et j'essaie de comprendre sa mise en œuvre. Voici la méthode de décodage valeur longue :
@Override
public long readLong() throws IOException {
ensureBounds(10);
int b = buf[pos++] & 0xff;
int n = b & 0x7f;
long l;
if (b > 0x7f) {
b = buf[pos++] & 0xff;
n ^= (b & 0x7f) << 7;
if (b > 0x7f) {
b = buf[pos++] & 0xff;
n ^= (b & 0x7f) << 14;
if (b > 0x7f) {
b = buf[pos++] & 0xff;
n ^= (b & 0x7f) << 21;
if (b > 0x7f) {
// only the low 28 bits can be set, so this won't carry
// the sign bit to the long
l = innerLongDecode((long)n);
} else {
l = n;
}
} else {
l = n;
}
} else {
l = n;
}
} else {
l = n;
}
if (pos > limit) {
throw new EOFException();
}
return (l >>> 1) ^ -(l & 1); // back to two's-complement
}
La question est de savoir pourquoi vérifions-nous toujours si 0x7f
moins que l'octet que nous venons de lire?
Il s'agit d'une forme de compression de bits où le bit le plus significatif de chaque byte
est utilisé pour déterminer si un autre byte
doit être lu. Essentiellement, cela vous permet de coder des valeurs dans un nombre d'octets inférieur à ce qu'elles auraient normalement besoin. Cependant, il y a la mise en garde que, si le nombre est grand, alors plus que la quantité normale d'octets sera nécessaire. Par conséquent, cela réussit lorsque vous travaillez avec de petites valeurs.
Pour en venir à votre question, 0x7F
est 0111_1111
en binaire. Vous pouvez voir que le bit le plus significatif est utilisé comme bit indicateur.
C'est 0b1111111
(127), le plus grand nombre possible avec un btye non signé, en gardant un pour un indicateur.