Skip to content

Commit f9519c6

Browse files
committed
FEAT: Bincode - added command EncodedU64 (for variable-length integers)
1 parent 433d068 commit f9519c6

File tree

2 files changed

+48
-50
lines changed

2 files changed

+48
-50
lines changed

src/core/u-bincode.c

+35-50
Original file line numberDiff line numberDiff line change
@@ -208,20 +208,15 @@ system/standard/bincode: make object! [
208208
209209
***********************************************************************/
210210

211-
static REBCNT EncodedU32_Size(u32 value) {
212-
REBCNT count = 0;
213-
if (value == 0) return 1;
214-
else while (value > 0) {
215-
value = value >> 7;
216-
count++;
217-
}
211+
static REBCNT EncodedU64_Size(u64 value) {
212+
REBCNT count = 1;
213+
while ((value >>= 7) != 0) count++;
218214
return count;
219215
}
220216

221217
static REBCNT EncodedVINT_Size(REBU64 value) {
222218
REBCNT count = 1;
223-
REBU64 temp = value;
224-
while (temp >= (1ULL << (7 * count))) count++;
219+
while (value >= (1ULL << (7 * count))) count++;
225220
return count;
226221
}
227222

@@ -566,8 +561,9 @@ static REBCNT EncodedVINT_Size(REBU64 value) {
566561
goto error;
567562

568563
case SYM_ENCODEDU32:
564+
case SYM_ENCODEDU64:
569565
if (IS_INTEGER(next)) {
570-
count += EncodedU32_Size(VAL_UNT32(next));
566+
count += EncodedU64_Size(VAL_UNT64(next));
571567
continue;
572568
}
573569
goto error;
@@ -936,18 +932,21 @@ static REBCNT EncodedVINT_Size(REBU64 value) {
936932
break;
937933

938934
case SYM_ENCODEDU32:
939-
ASSERT_U32_RANGE(next);
940-
ulong = VAL_UNT32(next);
941-
if (ulong == 0) {
942-
n = 1;
943-
cp[0] = 0;
944-
} else {
945-
n = EncodedU32_Size(VAL_UNT32(next));
946-
for (u = 0; u < n-1; u++) {
947-
cp[u] = (char)(128 + ((ulong >> (u * 7)) & 127));
948-
}
949-
cp[n-1] = (char)((ulong >> ((n-1) * 7)) & 255);
935+
case SYM_ENCODEDU64:
936+
if (cmd == SYM_ENCODEDU32) {
937+
ASSERT_U32_RANGE(next);
938+
u = (u64)VAL_UNT32(next);
939+
}
940+
else {
941+
u = VAL_UNT64(next);
950942
}
943+
n = 0;
944+
do {
945+
cp[n] = (char)(u & 0x7F); // Take the lowest 7 bits of the value
946+
u >>= 7; // Shift the value right by 7 bits
947+
if (u != 0) cp[n] |= 0x80; // Set the continuation bit if there are more bytes to write
948+
n++;
949+
} while (u != 0);
951950
break;
952951

953952
case SYM_VINT:
@@ -1258,37 +1257,23 @@ static REBCNT EncodedVINT_Size(REBU64 value) {
12581257
VAL_INDEX(temp) = 0;
12591258
break;
12601259
case SYM_ENCODEDU32:
1261-
ASSERT_READ_SIZE(value, cp, ep, 1);
1262-
u = (u64)cp[0];
1263-
if (!(u & 0x00000080)) {
1264-
n = 1;
1265-
goto setEnU32Result;
1266-
}
1267-
ASSERT_READ_SIZE(value, cp, ep, 2);
1268-
u = (u & 0x0000007f) | (u64)cp[1] << 7;
1269-
if (!(u & 0x00004000)) {
1270-
n = 2;
1271-
goto setEnU32Result;
1272-
}
1273-
ASSERT_READ_SIZE(value, cp, ep, 3);
1274-
u = (u & 0x00003fff) | (u64)cp[2] << 14;
1275-
if (!(u & 0x00200000)) {
1276-
n = 3;
1277-
goto setEnU32Result;
1278-
}
1279-
ASSERT_READ_SIZE(value, cp, ep, 4);
1280-
u = (u & 0x001fffff) | (u64)cp[3] << 21;
1281-
if (!(u & 0x10000000)) {
1282-
n = 4;
1283-
goto setEnU32Result;
1284-
}
1285-
ASSERT_READ_SIZE(value, cp, ep, 5);
1286-
u = (u & 0x0fffffff) | (u64)cp[4] << 28;
1287-
n = 5;
1288-
setEnU32Result:
1260+
case SYM_ENCODEDU64: {
1261+
REBCNT shift = 0;
1262+
REBYTE byte = 0;
1263+
n = 0;
1264+
u = 0;
1265+
do {
1266+
ASSERT_READ_SIZE(value, cp, ep, n+1);
1267+
byte = cp[n];
1268+
u |= (u64)(byte & 0x7F) << shift;
1269+
shift += 7;
1270+
n++;
1271+
} while ((byte & 0x80) != 0);
12891272
VAL_SET(temp, REB_INTEGER);
1290-
VAL_UNT64(temp) = u & 0xffffffff; // limits result to 32 bit unsigned integer!
1273+
if (cmd == SYM_ENCODEDU32) u &= 0xFFFFFFFF;
1274+
VAL_UNT64(temp) = u;
12911275
break;
1276+
}
12921277
case SYM_UB:
12931278
next = ++value;
12941279
if (IS_GET_WORD(next)) next = Get_Var(next);

src/tests/units/bincode-test.r3

+13
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,19 @@ is-protected-error?: func[code][
335335
--assert [0 1 128 129 130 2214768806] = binary/read b [
336336
EncodedU32 EncodedU32 EncodedU32 EncodedU32 EncodedU32 EncodedU32]
337337

338+
--test-- "BinCode - EncodedU64"
339+
b: binary/init none 16
340+
binary/write b [
341+
EncodedU64 0
342+
EncodedU64 0#0102030405
343+
EncodedU64 0#7FFFFFFFFFFF
344+
EncodedU64 0#7FFFFFFFFFFFFF
345+
EncodedU64 0#7FFFFFFFFFFFFFFF
346+
]
347+
--assert b/buffer = #{0085888C9010FFFFFFFFFFFF1FFFFFFFFFFFFFFF3FFFFFFFFFFFFFFFFF7F}
348+
--assert [0 0#0102030405 0#7FFFFFFFFFFF 0#7FFFFFFFFFFFFF 0#7FFFFFFFFFFFFFFF] = binary/read b [
349+
EncodedU64 EncodedU64 EncodedU64 EncodedU64 EncodedU64]
350+
338351
--test-- "BinCode - VINT"
339352
;; Another variable-length integer encoding (used in EBML/Matroska files)
340353
b: binary/init none 16

0 commit comments

Comments
 (0)