Skip to content

Commit 159b82f

Browse files
committed
FEAT: bincode - added zero-based ATz and INDEXz commands
1 parent 85fb9b6 commit 159b82f

File tree

2 files changed

+44
-13
lines changed

2 files changed

+44
-13
lines changed

src/core/u-bincode.c

+17-12
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ static REBCNT EncodedU32_Size(u32 value) {
239239
REBCNT n, count, index, tail, tail_new;
240240
REBDEC dbl;
241241
REBD32 d32;
242+
REBCNT cmd;
242243
i32 i, len;
243244
u64 u;
244245
i64 si;
@@ -425,8 +426,8 @@ static REBCNT EncodedU32_Size(u32 value) {
425426
Set_Binary(DS_TOP, Encode_UTF8_Value(next, VAL_LEN(next), 0));
426427
next = DS_POP;
427428
}
428-
429-
switch (VAL_WORD_CANON(data)) {
429+
cmd = VAL_WORD_CANON(data);
430+
switch (cmd) {
430431
case SYM_SI8:
431432
case SYM_UI8:
432433
if (IS_INTEGER(next) || IS_CHAR(next)) {
@@ -471,11 +472,13 @@ static REBCNT EncodedU32_Size(u32 value) {
471472
}
472473
goto error;
473474
case SYM_AT:
475+
case SYM_ATZ:
474476
if (IS_INTEGER(next)) {
475477
if (count > tail) tail = count;
476-
// AT is using ABSOLUTE positioning, so it cannot be < 1 (one-indexed)
477-
if(VAL_INT32(next) < 1) Trap1(RE_OUT_OF_RANGE, next);
478-
count = VAL_INT32(next) - 1;
478+
i = (cmd == SYM_AT ? 1 : 0);
479+
// AT is using ABSOLUTE positioning, so it cannot be < 1 (one-indexed) or < 0 (zero-based)
480+
if(VAL_INT32(next) < i) Trap1(RE_OUT_OF_RANGE, next);
481+
count = VAL_INT32(next) - i;
479482
continue;
480483
}
481484
goto error;
@@ -584,7 +587,7 @@ static REBCNT EncodedU32_Size(u32 value) {
584587
value++; //skip optional INDEX word...
585588
if (
586589
(VAL_TYPE(value) != REB_WORD) ||
587-
(VAL_WORD_CANON(value) != SYM_INDEX)
590+
(VAL_WORD_CANON(value) != SYM_INDEX && VAL_WORD_CANON(value) != SYM_INDEXZ)
588591
) {
589592
value--; //... or revert it
590593
}
@@ -655,8 +658,8 @@ static REBCNT EncodedU32_Size(u32 value) {
655658
Set_Binary(DS_TOP, Encode_UTF8_Value(next, VAL_LEN(next), 0));
656659
next = DS_POP;
657660
}
658-
659-
switch (VAL_WORD_CANON(data)) {
661+
cmd = VAL_WORD_CANON(data);
662+
switch (cmd) {
660663
case SYM_UI8:
661664
ASSERT_UI_RANGE(next, 0xFF);
662665
write_ui8:
@@ -891,7 +894,8 @@ static REBCNT EncodedU32_Size(u32 value) {
891894
break;
892895

893896
case SYM_AT:
894-
VAL_INDEX(buffer_write) = VAL_INT32(next) - 1;
897+
case SYM_ATZ:
898+
VAL_INDEX(buffer_write) = VAL_INT32(next) - (cmd == SYM_AT ? 1 : 0);
895899
cp = BIN_DATA(bin) + VAL_INDEX(buffer_write);
896900
n = 0;
897901
break;
@@ -1057,7 +1061,6 @@ static REBCNT EncodedU32_Size(u32 value) {
10571061
DS_PUSH_NONE;
10581062
temp = DS_TOP;
10591063
REBINT ssp = DSP; // starting stack pointer
1060-
REBINT cmd;
10611064

10621065
for (; NOT_END(value); value++) {
10631066
n = 0;
@@ -1452,18 +1455,20 @@ static REBCNT EncodedU32_Size(u32 value) {
14521455
VAL_INDEX(buffer_read) += 4;
14531456
goto readNBytes;
14541457
case SYM_AT:
1458+
case SYM_ATZ:
14551459
// uses absolute positioning from series HEAD!
14561460
next = ++value;
14571461
if (IS_GET_WORD(next)) next = Get_Var(next);
14581462
if (!IS_INTEGER(next)) Trap1(RE_INVALID_SPEC, value);
1459-
i = VAL_INT32(next) - 1;
1463+
i = VAL_INT32(next) - (cmd == SYM_AT ? 1 : 0);
14601464
ASSERT_INDEX_RANGE(buffer_read, i, value);
14611465
VAL_INDEX(buffer_read) = i;
14621466
cp = BIN_DATA(bin) + VAL_INDEX(buffer_read);
14631467
continue;
14641468
case SYM_INDEX:
1469+
case SYM_INDEXZ:
14651470
VAL_SET(temp, REB_INTEGER);
1466-
SET_INT32(temp, VAL_INDEX(buffer_read) + 1);
1471+
SET_INT32(temp, VAL_INDEX(buffer_read)) + (cmd == SYM_INDEX ? 1 : 0);
14671472
n = 0;
14681473
break;
14691474
case SYM_SKIP:

src/tests/units/bincode-test.r3

+27-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ is-protected-error?: func[code][
175175
--assert #{2AFF} = b/buffer
176176

177177
--test-- "BinCode - AT"
178-
;AT is using absolute positioning
178+
;AT is using absolute positioning (one-based)
179179
b: binary 8
180180

181181
binary/write b [AT 4 UI8 4]
@@ -191,6 +191,32 @@ is-protected-error?: func[code][
191191
binary/read b [AT 4 i: UI8] --assert i = 4
192192
--assert is-range-error? [binary/read b [AT 5 i: UI8]]
193193
--assert is-range-error? [binary/read b [AT -1 i: UI8]]
194+
195+
--test-- "BinCode - ATz"
196+
;ATz is using absolute positioning (zero-based)
197+
b: binary 8
198+
199+
binary/write b [ATz 3 UI8 4]
200+
binary/write b [ATz 2 UI8 3]
201+
binary/write b [ATz 1 UI8 2]
202+
binary/write b [ATz 0 UI8 1]
203+
--assert is-range-error? [binary/write b [ATz -1 UI8 1]]
204+
--assert #{01020304} = b/buffer
205+
i: 0
206+
binary/read b [ATz 0 i: UI8] --assert i = 1
207+
binary/read b [ATz 1 i: UI8] --assert i = 2
208+
binary/read b [ATz 2 i: UI8] --assert i = 3
209+
binary/read b [ATz 3 i: UI8] --assert i = 4
210+
--assert is-range-error? [binary/read b [ATz 4 i: UI8]]
211+
--assert is-range-error? [binary/read b [ATz -1 i: UI8]]
212+
213+
--test-- "BinCode - INDEX & INDEXz"
214+
b: binary #{01020304}
215+
--assert [1 0] = binary/read b [INDEX INDEXz]
216+
--assert [2 1] = binary/read b [AT 2 INDEX INDEXz]
217+
--assert [4 3] = binary/read b [ATz 3 INDEX INDEXz]
218+
binary/read b [AT 4 i: INDEX j: INDEXz]
219+
--assert all [i = 4 j = 3]
194220

195221
--test-- "BinCode - SKIP"
196222
;SKIP is using relative positioning

0 commit comments

Comments
 (0)