Skip to content

Commit

Permalink
FEAT: Bincode - added command VINT (for variable-length integers)
Browse files Browse the repository at this point in the history
  • Loading branch information
Oldes committed Jun 7, 2024
1 parent e1ee49e commit 3cb158b
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
47 changes: 47 additions & 0 deletions src/core/u-bincode.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ static REBCNT EncodedU32_Size(u32 value) {
return count;
}

static REBCNT EncodedVINT_Size(REBU64 value) {
REBCNT count = 1;
REBU64 temp = value;
while (temp >= (1ULL << (7 * count))) count++;
return count;
}

/***********************************************************************
**
*/ REBNATIVE(binary)
Expand Down Expand Up @@ -565,6 +572,13 @@ static REBCNT EncodedU32_Size(u32 value) {
}
goto error;

case SYM_VINT:
if (IS_INTEGER(next)) {
count += EncodedVINT_Size(VAL_UNT64(next));
continue;
}
goto error;

case SYM_FLOAT:
case SYM_F32:
case SYM_F32LE:
Expand Down Expand Up @@ -936,6 +950,16 @@ static REBCNT EncodedU32_Size(u32 value) {
}
break;

case SYM_VINT:
u = VAL_UNT64(next);
n = EncodedVINT_Size(u);
for (i = n-1; i > 0; i--) {
cp[i] = (char)(u & 0xFF);
u >>= 8;
}
cp[0] = (char)(u | (0x80 >> (n-1)));
break;

case SYM_UNIXTIME_NOW:
value--; // no args
n = 4;
Expand Down Expand Up @@ -1651,6 +1675,29 @@ static REBCNT EncodedU32_Size(u32 value) {
VAL_INDEX(buffer_write) = MAX(0, (REBI64)VAL_INDEX(buffer_write) - VAL_INDEX(buffer_read));
VAL_INDEX(buffer_read) = 0;
continue;

case SYM_VINT: {
// A variable-length format for positive integers
ASSERT_READ_SIZE(value, cp, ep, 1);
int mask = 0x80;
n = 1;
// Determine the length of the VINT
while (mask) {
if (cp[0] & mask) break;
mask >>= 1;
n++;
}
// Extract the VINT value
ASSERT_READ_SIZE(value, cp, ep, n);
u = (u64)(cp[0] & (0xFF >> n));
for (int i = 1; i < n; i++) {
u = (u << 8) | cp[i];
}
VAL_SET(temp, REB_INTEGER);
VAL_UNT64(temp) = u;
break;
}

default:
Trap1(RE_INVALID_SPEC, value);
}
Expand Down
15 changes: 15 additions & 0 deletions src/tests/units/bincode-test.r3
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,21 @@ is-protected-error?: func[code][
--assert [0 1 128 129 130 2214768806] = binary/read b [
EncodedU32 EncodedU32 EncodedU32 EncodedU32 EncodedU32 EncodedU32]

--test-- "BinCode - VINT"
;; Another variable-length integer encoding (used in EBML/Matroska files)
b: binary/init none 16
binary/write b [
VINT 0
VINT 1
VINT 128
VINT 129
VINT 130
VINT 2214768806
]
--assert b/buffer = #{8081408040814082088402B0A6}
--assert [0 1 128 129 130 2214768806] = binary/read b [
VINT VINT VINT VINT VINT VINT]

--test-- "BinCode - BITSET8, BITSET16, BITSET32 (read)"
binary/read #{81800180000001} [
f8: BITSET8
Expand Down

0 comments on commit 3cb158b

Please sign in to comment.