-
Notifications
You must be signed in to change notification settings - Fork 0
/
dtinyvbyte.pas
73 lines (63 loc) · 1.67 KB
/
dtinyvbyte.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
unit dtinyvbyte;
// tiny variable byte length encoder/decoder (vbyte)
// - rlyeh, public domain | wtrmrkrlyeh
// - ported to pascal by Doj
{$MODE FPC}
{$MODESWITCH DEFAULTPARAMETERS}
{$MODESWITCH OUT}
{$MODESWITCH RESULT}
interface
const
VBYTE_MIN_REQ_BYTES = 1;
VBYTE_MAX_REQ_BYTES = 10;
function vbuencode(Buffer: PByte; Value: UInt64): UInt64;
function vbudecode(Value: PUInt64; Buffer: PByte): UInt64;
function vbiencode(buffer: PUInt8; value: Int64): UInt64;
function vbidecode(value: PInt64; buffer: PUInt8): UInt64;
implementation
function vbuencode(Buffer: PByte; Value: UInt64): UInt64;
var
Buffer0: PByte;
begin
// 7-bit packing. MSB terminates stream
Buffer0 := Buffer;
repeat
Buffer^ := Byte($80 or (Value and $7f));
Inc(Buffer);
Value := Value shr 7;
until value <= 0;
(Buffer - 1)^ := (Buffer - 1)^ xor $80;
Exit(Buffer - Buffer0);
end;
function vbudecode(Value: PUInt64; Buffer: PByte): UInt64;
var
Buffer0: PByte;
_out, j: UInt64;
begin
// 7-bit unpacking. MSB terminates stream
Buffer0 := Buffer;
_out := 0;
j := 0;
repeat
_out := _out or ((UInt64(Buffer^) and $7f) shl j);
Inc(Buffer);
Inc(j, 7);
until (Buffer - 1)^ and $80 = 0;
Value^ := _out;
Exit(Buffer - Buffer0);
end;
function vbiencode(buffer: PUInt8; value: Int64): UInt64;
begin
// convert sign|magnitude to magnitude|sign, encode unsigned
Exit(vbuencode(buffer, UInt64(SarInt64(value, 63) xor (value shl 1))));
end;
function vbidecode(value: PInt64; buffer: PUInt8): UInt64;
var
nv: UInt64;
begin
// decode unsigned
Result := vbudecode(@nv, buffer);
// convert magnitude|sign to sign|magnitude
value^ := Int64((nv shr 1) xor -(nv and 1));
end;
end.