Skip to content

Commit ea06082

Browse files
committed
FEAT: added support for EncodedU32 in BINARY's read and write
EncodedU32 is used in Adobe's SWF files. It defines an 32-bit unsigned integer as a sequence of 1 to 5 bytes. The most significant bit of a byte indicates if the next byte is also part of the value. The byte are ordered low to high.
1 parent 5e975ad commit ea06082

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

src/core/u-bincode.c

+69-1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,17 @@ system/standard/bincode: make object! [
114114
]
115115
116116
***********************************************************************/
117+
118+
static REBCNT EncodedU32_Size(u32 value) {
119+
REBCNT count = 0;
120+
if (value == 0) return 1;
121+
else while (value > 0) {
122+
value = value >> 7;
123+
count++;
124+
}
125+
return count;
126+
}
127+
117128
/***********************************************************************
118129
**
119130
*/ REBNATIVE(binary)
@@ -153,7 +164,8 @@ system/standard/bincode: make object! [
153164
REBYTE *cp, *bp, *ep;
154165
REBCNT n, count, index, tail, tail_new;
155166
i32 i, len;
156-
//u64 u;
167+
u64 u;
168+
u32 ulong;
157169

158170
REBVAL *value, *next;
159171
REBVAL *data;
@@ -408,6 +420,14 @@ system/standard/bincode: make object! [
408420
continue;
409421
}
410422
goto error;
423+
424+
case SYM_ENCODEDU32:
425+
if (IS_INTEGER(next)) {
426+
count += EncodedU32_Size(VAL_INT64(next));
427+
continue;
428+
}
429+
goto error;
430+
411431
case SYM_UNIXTIME_NOW:
412432
case SYM_UNIXTIME_NOW_LE:
413433
value--; //there is no argument so no next
@@ -654,6 +674,22 @@ system/standard/bincode: make object! [
654674
cp = BIN_DATA(bin) + VAL_INDEX(buffer_write);
655675
n = 0;
656676
break;
677+
678+
case SYM_ENCODEDU32:
679+
ASSERT_U32_RANGE(next);
680+
ulong = (u32)VAL_INT64(next);
681+
if (ulong == 0) {
682+
n = 1;
683+
cp[0] = 0;
684+
} else {
685+
n = EncodedU32_Size(VAL_INT64(next));
686+
for (u = 0; u < n-1; u++) {
687+
cp[u] = (char)(128 + ((ulong >> (u * 7)) & 127));
688+
}
689+
cp[n-1] = (char)((ulong >> ((n-1) * 7)) & 255);
690+
}
691+
break;
692+
657693
case SYM_UNIXTIME_NOW:
658694
value--; // no args
659695
n = 4;
@@ -879,6 +915,38 @@ system/standard/bincode: make object! [
879915
}
880916
n++;
881917
break;
918+
case SYM_ENCODEDU32:
919+
ASSERT_READ_SIZE(value, cp, ep, 1);
920+
u = (u64)cp[0];
921+
if (!(u & 0x00000080)) {
922+
n = 1;
923+
goto setEnU32Result;
924+
}
925+
ASSERT_READ_SIZE(value, cp, ep, 2);
926+
u = (u & 0x0000007f) | cp[1] << 7;
927+
if (!(u & 0x00004000)) {
928+
n = 2;
929+
goto setEnU32Result;
930+
}
931+
ASSERT_READ_SIZE(value, cp, ep, 3);
932+
u = (u & 0x00003fff) | cp[2] << 14;
933+
if (!(u & 0x00200000)) {
934+
n = 3;
935+
goto setEnU32Result;
936+
}
937+
ASSERT_READ_SIZE(value, cp, ep, 4);
938+
u = (u & 0x001fffff) | cp[3] << 21;
939+
if (!(u & 0x10000000)) {
940+
n = 4;
941+
goto setEnU32Result;
942+
}
943+
ASSERT_READ_SIZE(value, cp, ep, 5);
944+
u = (u & 0x0fffffff) | cp[4] << 28;
945+
n = 5;
946+
setEnU32Result:
947+
VAL_SET(temp, REB_INTEGER);
948+
VAL_UNT64(temp) = u & 0xffffffff; // limits result to 32 bit unsigned integer!
949+
break;
882950
case SYM_UB:
883951
next = ++value;
884952
if (IS_GET_WORD(next)) next = Get_Var(next);

src/tests/units/bincode-test.r3

+14
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,20 @@ is-protected-error?: func[code][
230230
b: binary 2#{01011011 10110011 11111111}
231231
--assert [2 -2 3 -3 255] = binary/read b [SB 3 SB 3 UB 2 SB 4 ALIGN UI8]
232232

233+
--test-- "BinCode - EncodedU32"
234+
b: binary/init none 16
235+
binary/write b [
236+
EncodedU32 0
237+
EncodedU32 1
238+
EncodedU32 128
239+
EncodedU32 129
240+
EncodedU32 130
241+
EncodedU32 2214768806
242+
]
243+
--assert b/buffer = #{0001800181018201A6E18AA008}
244+
--assert [0 1 128 129 130 2214768806] = binary/read b [
245+
EncodedU32 EncodedU32 EncodedU32 EncodedU32 EncodedU32 EncodedU32]
246+
233247
===end-group===
234248

235249

0 commit comments

Comments
 (0)