-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add variable-length-quantity exercise (#116)
- Loading branch information
1 parent
722d6f7
commit 7ffa936
Showing
12 changed files
with
3,898 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
exercises/practice/variable-length-quantity/.docs/instructions.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# Instructions | ||
|
||
Implement variable length quantity encoding and decoding. | ||
|
||
The goal of this exercise is to implement [VLQ][vlq] encoding/decoding. | ||
|
||
In short, the goal of this encoding is to encode integer values in a way that would save bytes. | ||
Only the first 7 bits of each byte are significant (right-justified; sort of like an ASCII byte). | ||
So, if you have a 32-bit value, you have to unpack it into a series of 7-bit bytes. | ||
Of course, you will have a variable number of bytes depending upon your integer. | ||
To indicate which is the last byte of the series, you leave bit #7 clear. | ||
In all of the preceding bytes, you set bit #7. | ||
|
||
So, if an integer is between `0-127`, it can be represented as one byte. | ||
Although VLQ can deal with numbers of arbitrary sizes, for this exercise we will restrict ourselves to only numbers that fit in a 32-bit unsigned integer. | ||
Here are examples of integers as 32-bit values, and the variable length quantities that they translate to: | ||
|
||
```text | ||
NUMBER VARIABLE QUANTITY | ||
00000000 00 | ||
00000040 40 | ||
0000007F 7F | ||
00000080 81 00 | ||
00002000 C0 00 | ||
00003FFF FF 7F | ||
00004000 81 80 00 | ||
00100000 C0 80 00 | ||
001FFFFF FF FF 7F | ||
00200000 81 80 80 00 | ||
08000000 C0 80 80 00 | ||
0FFFFFFF FF FF FF 7F | ||
``` | ||
|
||
[vlq]: https://en.wikipedia.org/wiki/Variable-length_quantity |
19 changes: 19 additions & 0 deletions
19
exercises/practice/variable-length-quantity/.meta/config.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"authors": [ | ||
"keiravillekode" | ||
], | ||
"files": { | ||
"solution": [ | ||
"variable_length_quantity.s" | ||
], | ||
"test": [ | ||
"variable_length_quantity_test.c" | ||
], | ||
"example": [ | ||
".meta/example.s" | ||
] | ||
}, | ||
"blurb": "Implement variable length quantity encoding and decoding.", | ||
"source": "A poor Splice developer having to implement MIDI encoding/decoding.", | ||
"source_url": "https://splice.com" | ||
} |
80 changes: 80 additions & 0 deletions
80
exercises/practice/variable-length-quantity/.meta/example.s
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
.text | ||
.globl encode | ||
.globl decode | ||
|
||
/* extern size_t encode(uint8_t *buffer, const uint32_t *integers, size_t integer_count); */ | ||
encode: | ||
lsl x2, x2, #2 /* size of integers array, in bytes */ | ||
add x2, x1, x2 /* end of integers */ | ||
mov x3, x0 /* start of output */ | ||
|
||
.encode_loop: | ||
cmp x1, x2 | ||
beq .encode_end | ||
|
||
ldr w4, [x1], #4 | ||
cmp w4, #127 | ||
bls .one | ||
|
||
lsr w5, w4, #7 | ||
cmp w5, #127 | ||
bls .two | ||
|
||
lsr w6, w5, #7 | ||
cmp w6, #127 | ||
bls .three | ||
|
||
lsr w7, w6, #7 | ||
cmp w7, #127 | ||
bls .four | ||
|
||
lsr w8, w7, #7 | ||
orr w8, w8, #128 | ||
strb w8, [x0], #1 | ||
|
||
.four: | ||
orr w7, w7, #128 | ||
strb w7, [x0], #1 | ||
|
||
.three: | ||
orr w6, w6, #128 | ||
strb w6, [x0], #1 | ||
|
||
.two: | ||
orr w5, w5, #128 | ||
strb w5, [x0], #1 | ||
|
||
.one: | ||
and w4, w4, #127 | ||
strb w4, [x0], #1 | ||
b .encode_loop | ||
|
||
.encode_end: | ||
sub x0, x0, x3 | ||
ret | ||
|
||
/* extern size_t decode(uint32_t *buffer, const uint8_t *integers, size_t integer_count); */ | ||
decode: | ||
add x2, x1, x2 /* end of integers array */ | ||
mov x3, x0 /* start of output */ | ||
|
||
.loop: | ||
mov w4, wzr | ||
cmp x1, x2 | ||
beq .end | ||
|
||
.read: | ||
ldrb w5, [x1], #1 | ||
lsl w4, w4, #7 | ||
and w6, w5, #127 | ||
orr w4, w4, w6 | ||
tst w5, #128 | ||
bne .read | ||
|
||
str w4, [x0], #4 | ||
b .loop | ||
|
||
.end: | ||
sub x0, x0, x3 /* length of output, in bytes */ | ||
lsr x0, x0, #2 /* number of uint32_t values output */ | ||
ret |
90 changes: 90 additions & 0 deletions
90
exercises/practice/variable-length-quantity/.meta/tests.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# This is an auto-generated file. | ||
# | ||
# Regenerating this file via `configlet sync` will: | ||
# - Recreate every `description` key/value pair | ||
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications | ||
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) | ||
# - Preserve any other key/value pair | ||
# | ||
# As user-added comments (using the # character) will be removed when this file | ||
# is regenerated, comments can be added via a `comment` key. | ||
|
||
[35c9db2e-f781-4c52-b73b-8e76427defd0] | ||
description = "Encode a series of integers, producing a series of bytes. -> zero" | ||
|
||
[be44d299-a151-4604-a10e-d4b867f41540] | ||
description = "Encode a series of integers, producing a series of bytes. -> arbitrary single byte" | ||
|
||
[ea399615-d274-4af6-bbef-a1c23c9e1346] | ||
description = "Encode a series of integers, producing a series of bytes. -> largest single byte" | ||
|
||
[77b07086-bd3f-4882-8476-8dcafee79b1c] | ||
description = "Encode a series of integers, producing a series of bytes. -> smallest double byte" | ||
|
||
[63955a49-2690-4e22-a556-0040648d6b2d] | ||
description = "Encode a series of integers, producing a series of bytes. -> arbitrary double byte" | ||
|
||
[29da7031-0067-43d3-83a7-4f14b29ed97a] | ||
description = "Encode a series of integers, producing a series of bytes. -> largest double byte" | ||
|
||
[3345d2e3-79a9-4999-869e-d4856e3a8e01] | ||
description = "Encode a series of integers, producing a series of bytes. -> smallest triple byte" | ||
|
||
[5df0bc2d-2a57-4300-a653-a75ee4bd0bee] | ||
description = "Encode a series of integers, producing a series of bytes. -> arbitrary triple byte" | ||
|
||
[f51d8539-312d-4db1-945c-250222c6aa22] | ||
description = "Encode a series of integers, producing a series of bytes. -> largest triple byte" | ||
|
||
[da78228b-544f-47b7-8bfe-d16b35bbe570] | ||
description = "Encode a series of integers, producing a series of bytes. -> smallest quadruple byte" | ||
|
||
[11ed3469-a933-46f1-996f-2231e05d7bb6] | ||
description = "Encode a series of integers, producing a series of bytes. -> arbitrary quadruple byte" | ||
|
||
[d5f3f3c3-e0f1-4e7f-aad0-18a44f223d1c] | ||
description = "Encode a series of integers, producing a series of bytes. -> largest quadruple byte" | ||
|
||
[91a18b33-24e7-4bfb-bbca-eca78ff4fc47] | ||
description = "Encode a series of integers, producing a series of bytes. -> smallest quintuple byte" | ||
|
||
[5f34ff12-2952-4669-95fe-2d11b693d331] | ||
description = "Encode a series of integers, producing a series of bytes. -> arbitrary quintuple byte" | ||
|
||
[7489694b-88c3-4078-9864-6fe802411009] | ||
description = "Encode a series of integers, producing a series of bytes. -> maximum 32-bit integer input" | ||
|
||
[f9b91821-cada-4a73-9421-3c81d6ff3661] | ||
description = "Encode a series of integers, producing a series of bytes. -> two single-byte values" | ||
|
||
[68694449-25d2-4974-ba75-fa7bb36db212] | ||
description = "Encode a series of integers, producing a series of bytes. -> two multi-byte values" | ||
|
||
[51a06b5c-de1b-4487-9a50-9db1b8930d85] | ||
description = "Encode a series of integers, producing a series of bytes. -> many multi-byte values" | ||
|
||
[baa73993-4514-4915-bac0-f7f585e0e59a] | ||
description = "Decode a series of bytes, producing a series of integers. -> one byte" | ||
|
||
[72e94369-29f9-46f2-8c95-6c5b7a595aee] | ||
description = "Decode a series of bytes, producing a series of integers. -> two bytes" | ||
|
||
[df5a44c4-56f7-464e-a997-1db5f63ce691] | ||
description = "Decode a series of bytes, producing a series of integers. -> three bytes" | ||
|
||
[1bb58684-f2dc-450a-8406-1f3452aa1947] | ||
description = "Decode a series of bytes, producing a series of integers. -> four bytes" | ||
|
||
[cecd5233-49f1-4dd1-a41a-9840a40f09cd] | ||
description = "Decode a series of bytes, producing a series of integers. -> maximum 32-bit integer" | ||
|
||
[e7d74ba3-8b8e-4bcb-858d-d08302e15695] | ||
description = "Decode a series of bytes, producing a series of integers. -> incomplete sequence causes error" | ||
include = false | ||
|
||
[aa378291-9043-4724-bc53-aca1b4a3fcb6] | ||
description = "Decode a series of bytes, producing a series of integers. -> incomplete sequence causes error, even if value is zero" | ||
include = false | ||
|
||
[a91e6f5a-c64a-48e3-8a75-ce1a81e0ebee] | ||
description = "Decode a series of bytes, producing a series of integers. -> multiple values" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
AS = aarch64-linux-gnu-as | ||
CC = aarch64-linux-gnu-gcc | ||
|
||
CFLAGS = -g -Wall -Wextra -pedantic -Werror | ||
LDFLAGS = | ||
|
||
ALL_LDFLAGS = -pie -Wl,--fatal-warnings | ||
|
||
ALL_CFLAGS = -std=c99 -fPIE $(CFLAGS) | ||
ALL_LDFLAGS += $(LDFLAGS) | ||
|
||
C_OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) | ||
AS_OBJS = $(patsubst %.s,%.o,$(wildcard *.s)) | ||
ALL_OBJS = $(filter-out example.o,$(C_OBJS) $(AS_OBJS) vendor/unity.o) | ||
|
||
CC_CMD = $(CC) $(ALL_CFLAGS) -c -o $@ $< | ||
|
||
all: tests | ||
qemu-aarch64 -L /usr/aarch64-linux-gnu ./$< | ||
|
||
tests: $(ALL_OBJS) | ||
@$(CC) $(ALL_CFLAGS) $(ALL_LDFLAGS) -o $@ $(ALL_OBJS) | ||
|
||
%.o: %.s | ||
@$(AS) -o $@ $< | ||
|
||
%.o: %.c | ||
@$(CC_CMD) | ||
|
||
vendor/unity.o: vendor/unity.c vendor/unity.h vendor/unity_internals.h | ||
@$(CC_CMD) | ||
|
||
clean: | ||
@rm -f *.o vendor/*.o tests | ||
|
||
.PHONY: all clean |
9 changes: 9 additions & 0 deletions
9
exercises/practice/variable-length-quantity/variable_length_quantity.s
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
.text | ||
.globl encode | ||
.globl decode | ||
|
||
encode: | ||
ret | ||
|
||
decode: | ||
ret |
Oops, something went wrong.