Repair machineword reads

This commit is contained in:
Tony Garnock-Jones 2023-06-23 22:34:38 +02:00
parent ae02cff81d
commit 54b9bb6f25
1 changed files with 14 additions and 9 deletions

View File

@ -61,14 +61,18 @@ namespace Preserves {
return d;
}
boost::optional<uint64_t> next_unsigned(size_t n) {
boost::optional<Value<T>> next_machineword(size_t n, bool always_unsigned) {
uint8_t buf[n];
if (!next_chunk(buf, n)) return boost::none;
uint64_t v = 0;
for (size_t j = 0; j < n; j++) {
v = (v << 8) | buf[j];
if ((buf[0] & 0x80) && !always_unsigned) {
int64_t v = -1;
for (size_t j = 0; j < n; j++) v = (v << 8) | buf[j];
return Value<T>::from_int(v);
} else {
uint64_t v = 0;
for (size_t j = 0; j < n; j++) v = (v << 8) | buf[j];
return Value<T>::from_int(v);
}
return v;
}
boost::optional<Value<T>> next_bignum(size_t n) {
@ -115,12 +119,13 @@ namespace Preserves {
}
case BinaryTag::MediumInteger_lo ... BinaryTag::MediumInteger_hi: {
int n = int(tag) - int(BinaryTag::MediumInteger_lo) + 1;
if (n < 9) {
return next_unsigned(n).map([](uint64_t v) { return Value<T>::from_int(int64_t(v)); });
}
if (n < 9) return next_machineword(n, false);
if (n == 9) {
// We can handle this with uint64_t if it's unsigned and the first byte is 0.
if (i.get() == 0) return next_unsigned(8).map(Value<T>::from_unsigned);
if (i.peek() == 0) {
i.get();
return next_machineword(8, true);
}
}
return next_bignum(n);
}