Skip to content

Commit 642086b

Browse files
committed
FEAT: improving BinCode
* added possibility to specify number to bytes to read directly: `binary/read #{0102} 1` * added possibility to write FILE! and URL! types * added few missing UI*BYTES variants (also with little/big endian) - but that must be revisited later!
1 parent 1f9199a commit 642086b

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

src/core/u-bincode.c

+54-7
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ static REBCNT EncodedU32_Size(u32 value) {
208208
// /write "Write data into output buffer"
209209
// data [binary! block!] "Data dialect"
210210
// /read "Read data from the input buffer"
211-
// code [word! block!] "Input encoding"
211+
// code [word! block! integer!] "Input encoding"
212212
// /into "Put READ results in out block, instead of creating a new block"
213213
// out [block!] "Target block for results, when /into is used"
214214
// /with "Additional input argument"
@@ -420,8 +420,10 @@ static REBCNT EncodedU32_Size(u32 value) {
420420
Do_Path(&next, NULL);
421421
next = DS_POP; // volatile stack reference
422422
}
423-
if (IS_STRING(next)) {
424-
Set_Binary(next, Encode_UTF8_Value(next, VAL_LEN(next), 0));
423+
if (IS_STRING(next) || IS_FILE(next) || IS_URL(next)) {
424+
DS_PUSH_NONE;
425+
Set_Binary(DS_TOP, Encode_UTF8_Value(next, VAL_LEN(next), 0));
426+
next = DS_POP;
425427
}
426428

427429
switch (VAL_WORD_CANON(data)) {
@@ -492,20 +494,25 @@ static REBCNT EncodedU32_Size(u32 value) {
492494
break;
493495
case SYM_UI16BYTES:
494496
case SYM_UI16LEBYTES:
497+
case SYM_UI16BEBYTES:
495498
if (IS_BINARY(next)) {
496499
ASSERT_UIBYTES_RANGE(next, 0xFFFF);
497500
count += (2 + VAL_LEN(next));
498501
continue;
499502
}
500503
goto error;
501504
case SYM_UI24BYTES:
505+
case SYM_UI24LEBYTES:
506+
case SYM_UI24BEBYTES:
502507
if (IS_BINARY(next)) {
503508
ASSERT_UIBYTES_RANGE(next, 0xFFFFFF);
504509
count += (3 + VAL_LEN(next));
505510
continue;
506511
}
507512
goto error;
508513
case SYM_UI32BYTES:
514+
case SYM_UI32LEBYTES:
515+
case SYM_UI32BEBYTES:
509516
if (IS_BINARY(next)) {
510517
ASSERT_UIBYTES_RANGE(next, 0xFFFFFFFF);
511518
count += (4 + VAL_LEN(next));
@@ -643,8 +650,10 @@ static REBCNT EncodedU32_Size(u32 value) {
643650
Do_Path(&next, NULL);
644651
next = DS_POP; // volatile stack reference
645652
}
646-
if (IS_STRING(next)) {
647-
Set_Binary(next, Encode_UTF8_Value(next, VAL_LEN(next), 0));
653+
if (IS_STRING(next) || IS_FILE(next) || IS_URL(next)) {
654+
DS_PUSH_NONE;
655+
Set_Binary(DS_TOP, Encode_UTF8_Value(next, VAL_LEN(next), 0));
656+
next = DS_POP;
648657
}
649658

650659
switch (VAL_WORD_CANON(data)) {
@@ -771,6 +780,7 @@ static REBCNT EncodedU32_Size(u32 value) {
771780
VAL_INDEX(buffer_write)++; //for the length byte;
772781
break;
773782
case SYM_UI16BYTES:
783+
case SYM_UI16BEBYTES:
774784
n = VAL_LEN(next);
775785
bp = (REBYTE*)&n;
776786
#ifdef ENDIAN_LITTLE
@@ -796,24 +806,50 @@ static REBCNT EncodedU32_Size(u32 value) {
796806
break;
797807

798808
case SYM_UI24BYTES:
809+
case SYM_UI24BEBYTES:
799810
n = VAL_LEN(next);
800811
bp = (REBYTE*)&n;
801812
#ifdef ENDIAN_LITTLE
802813
cp[0] = bp[2]; cp[1] = bp[1]; cp[2] = bp[0];
803814
#else
804815
memcpy(cp, bp, 3);
816+
#endif
817+
cp += 3;
818+
memcpy(cp, VAL_BIN_AT(next), n);
819+
VAL_INDEX(buffer_write) += 3; //for the length byte;
820+
break;
821+
case SYM_UI24LEBYTES:
822+
n = VAL_LEN(next);
823+
bp = (REBYTE*)&n;
824+
#ifdef ENDIAN_LITTLE
825+
memcpy(cp, bp, 3);
826+
#else
827+
cp[0] = bp[2]; cp[1] = bp[1]; cp[2] = bp[0];
805828
#endif
806829
cp += 3;
807830
memcpy(cp, VAL_BIN_AT(next), n);
808831
VAL_INDEX(buffer_write) += 3; //for the length byte;
809832
break;
810833
case SYM_UI32BYTES:
834+
case SYM_UI32BEBYTES:
811835
n = VAL_LEN(next);
812836
bp = (REBYTE*)&n;
813837
#ifdef ENDIAN_LITTLE
814838
cp[0] = bp[3]; cp[1] = bp[2]; cp[2] = bp[1]; cp[3] = bp[0];
815839
#else
816840
memcpy(cp, bp, 4);
841+
#endif
842+
cp += 4;
843+
memcpy(cp, VAL_BIN_AT(next), n);
844+
VAL_INDEX(buffer_write) += 4; //for the length byte;
845+
break;
846+
case SYM_UI32LEBYTES:
847+
n = VAL_LEN(next);
848+
bp = (REBYTE*)&n;
849+
#ifdef ENDIAN_LITTLE
850+
memcpy(cp, bp, 4);
851+
#else
852+
cp[0] = bp[3]; cp[1] = bp[2]; cp[2] = bp[1]; cp[3] = bp[0];
817853
#endif
818854
cp += 4;
819855
memcpy(cp, VAL_BIN_AT(next), n);
@@ -978,6 +1014,17 @@ static REBCNT EncodedU32_Size(u32 value) {
9781014

9791015
inBit = IS_OBJECT(val_ctx) ? VAL_INT32(VAL_OBJ_VALUE(val_ctx, BINCODE_READ_BITMASK)): 0;
9801016

1017+
if (IS_INTEGER(val_read)) {
1018+
n = VAL_INT64(val_read);
1019+
ASSERT_READ_SIZE(val_read, cp, ep, n);
1020+
if(ref_into) {
1021+
Trap0(RE_FEATURE_NA);
1022+
}
1023+
Set_Binary(D_RET, Copy_Series_Part(bin, VAL_INDEX(buffer_read), n));
1024+
VAL_TAIL(D_RET) = n;
1025+
VAL_INDEX(buffer_read) += n;
1026+
return R_RET;
1027+
}
9811028
as_block = IS_BLOCK(val_read);
9821029

9831030
if(as_block) {
@@ -1237,7 +1284,7 @@ static REBCNT EncodedU32_Size(u32 value) {
12371284
if (nbits > 0) {
12381285
if (inBit == 0) inBit = 0x80;
12391286
// http://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
1240-
u64 m = 1U << (nbits - 1); // sign bit mask
1287+
u64 m = (u64)1 << (nbits - 1); // sign bit mask
12411288
nbits = 1 << nbits;
12421289
//if (nbits > 0) {
12431290
//printf("SB nbits: %i\n", nbits);
@@ -1326,7 +1373,7 @@ static REBCNT EncodedU32_Size(u32 value) {
13261373
VAL_SERIES(temp) = bin_new;
13271374
VAL_INDEX(temp) = 0;
13281375
if (cmd == SYM_STRING_BYTES) {
1329-
VAL_TAIL(temp) = strnlen(VAL_BIN(temp), n);
1376+
VAL_TAIL(temp) = strnlen(cs_cast(VAL_BIN(temp)), n);
13301377
}
13311378
}
13321379
break;

src/tests/units/bincode-test.r3

+17-1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ is-protected-error?: func[code][
141141
--test-- "BinCode - BYTES"
142142
--assert object? binary/write b [#{cafe}]
143143
--assert #{CAFE} = binary/read b 'bytes
144+
--assert object? binary/write b [BYTES %ščř%20 BYTES http://foo]
145+
--assert "ščř http://foo" = to string! binary/read b 'bytes
144146
--test-- "BinCode - UI8BYTES"
145147
--assert object? binary/write b [UI8BYTES #{cafe}]
146148
--assert #{02CAFE} = binary/read b 'bytes
@@ -241,6 +243,17 @@ is-protected-error?: func[code][
241243
--assert str = "test"
242244
--assert i = 42
243245

246+
--test-- "BinCode - read using integer argument"
247+
b: #{010203}
248+
--assert #{0102} = binary/read b 2
249+
--assert #{010203} = b
250+
--assert #{0203} = binary/read next b 2
251+
b: binary #{01020304}
252+
--assert #{0102} = binary/read b 2
253+
--assert #{0304} = binary/read b 2
254+
--assert error? try [binary/read b 2] ;value out of range
255+
256+
244257
--test-- "BinCode - bits (SB, UB, FB, ALIGN)"
245258
b: binary 2#{01011011 10110011 11111111}
246259
--assert [2 -2 3 -5 255] = binary/read b [SB 3 SB 3 UB 2 SB 4 ALIGN UI8]
@@ -350,7 +363,10 @@ is-protected-error?: func[code][
350363

351364
--test-- "BinCode - FLOAT16, FLOAT, DOUBLE (write/read NAN)"
352365
b: binary/write #{} [float16 1.#NaN float 1.#NaN double 1.#NaN]
353-
--assert b/buffer = #{007E0000C07F000000000000F87F}
366+
--assert found? find [
367+
#{007E0000C07F000000000000F87F}
368+
#{007E0000C0FF000000000000F8FF} ; when used clang compiler (should it be normalized?)
369+
] b/buffer
354370
--assert tail? b/buffer-write
355371
;@@ using MOLD as: 1.#nan <> 1.#nan
356372
--assert "[1.#NaN 1.#NaN 1.#NaN]" = mold binary/read b [float16 float double]

0 commit comments

Comments
 (0)