1 | /*
|
---|
2 | * This is a AssemblyScript port of the original Java version, which was written by
|
---|
3 | * Gil Tene as described in
|
---|
4 | * https://github.com/HdrHistogram/HdrHistogram
|
---|
5 | * and released to the public domain, as explained at
|
---|
6 | * http://creativecommons.org/publicdomain/zero/1.0/
|
---|
7 | */
|
---|
8 |
|
---|
9 | import ByteBuffer from "./ByteBuffer";
|
---|
10 |
|
---|
11 | /**
|
---|
12 | * This class provides encoding and decoding methods for writing and reading
|
---|
13 | * ZigZag-encoded LEB128-64b9B-variant (Little Endian Base 128) values to/from a
|
---|
14 | * {@link ByteBuffer}. LEB128's variable length encoding provides for using a
|
---|
15 | * smaller nuber of bytes for smaller values, and the use of ZigZag encoding
|
---|
16 | * allows small (closer to zero) negative values to use fewer bytes. Details
|
---|
17 | * on both LEB128 and ZigZag can be readily found elsewhere.
|
---|
18 | *
|
---|
19 | * The LEB128-64b9B-variant encoding used here diverges from the "original"
|
---|
20 | * LEB128 as it extends to 64 bit values: In the original LEB128, a 64 bit
|
---|
21 | * value can take up to 10 bytes in the stream, where this variant's encoding
|
---|
22 | * of a 64 bit values will max out at 9 bytes.
|
---|
23 | *
|
---|
24 | * As such, this encoder/decoder should NOT be used for encoding or decoding
|
---|
25 | * "standard" LEB128 formats (e.g. Google Protocol Buffers).
|
---|
26 | */
|
---|
27 | class ZigZagEncoding {
|
---|
28 | /**
|
---|
29 | * Writes a 64b value to the given buffer in LEB128 ZigZag encoded format
|
---|
30 | * (negative numbers not supported)
|
---|
31 | * @param buffer the buffer to write to
|
---|
32 | * @param value the value to write to the buffer
|
---|
33 | */
|
---|
34 | static encode(buffer: ByteBuffer, value: i64): void {
|
---|
35 | value = (value << 1) ^ (value >> 63);
|
---|
36 | if (value >>> 7 === 0) {
|
---|
37 | buffer.put(<u8>value);
|
---|
38 | } else {
|
---|
39 | buffer.put(<u8>((value & 0x7f) | 0x80));
|
---|
40 | if (value >>> 14 === 0) {
|
---|
41 | buffer.put(<u8>(value >>> 7));
|
---|
42 | } else {
|
---|
43 | buffer.put(<u8>((value >>> 7) | 0x80));
|
---|
44 | if (value >>> 21 === 0) {
|
---|
45 | buffer.put(<u8>(value >>> 14));
|
---|
46 | } else {
|
---|
47 | buffer.put(<u8>((value >>> 14) | 0x80));
|
---|
48 | if (value >>> 28 === 0) {
|
---|
49 | buffer.put(<u8>(value >>> 21));
|
---|
50 | } else {
|
---|
51 | buffer.put(<u8>((value >>> 21) | 0x80));
|
---|
52 | if (value >>> 35 === 0) {
|
---|
53 | buffer.put(<u8>(value >>> 28));
|
---|
54 | } else {
|
---|
55 | buffer.put(<u8>((value >>> 28) | 0x80));
|
---|
56 | if (value >>> 42 === 0) {
|
---|
57 | buffer.put(<u8>(value >>> 35));
|
---|
58 | } else {
|
---|
59 | buffer.put(<u8>((value >>> 35) | 0x80));
|
---|
60 | if (value >>> 49 === 0) {
|
---|
61 | buffer.put(<u8>(value >>> 42));
|
---|
62 | } else {
|
---|
63 | buffer.put(<u8>((value >>> 42) | 0x80));
|
---|
64 | if (value >>> 56 === 0) {
|
---|
65 | buffer.put(<u8>(value >>> 49));
|
---|
66 | } else {
|
---|
67 | buffer.put(<u8>((value >>> 49) | 0x80));
|
---|
68 | buffer.put(<u8>(value >>> 56));
|
---|
69 | }
|
---|
70 | }
|
---|
71 | }
|
---|
72 | }
|
---|
73 | }
|
---|
74 | }
|
---|
75 | }
|
---|
76 | }
|
---|
77 | }
|
---|
78 |
|
---|
79 | /**
|
---|
80 | * Read an LEB128-64b9B ZigZag encoded long value from the given buffer
|
---|
81 | * (negative numbers not supported)
|
---|
82 | * @param buffer the buffer to read from
|
---|
83 | * @return the value read from the buffer
|
---|
84 | */
|
---|
85 | static decode(buffer: ByteBuffer): i64 {
|
---|
86 | let v = <i64>buffer.get();
|
---|
87 | let value: i64 = (<i64>v) & (<i64>0x7f);
|
---|
88 | if ((v & 0x80) != 0) {
|
---|
89 | v = buffer.get();
|
---|
90 | value |= (v & 0x7f) << 7;
|
---|
91 | if ((v & 0x80) != 0) {
|
---|
92 | v = buffer.get();
|
---|
93 | value |= (v & 0x7f) << 14;
|
---|
94 | if ((v & 0x80) != 0) {
|
---|
95 | v = buffer.get();
|
---|
96 | value |= (v & 0x7f) << 21;
|
---|
97 | if ((v & 0x80) != 0) {
|
---|
98 | v = buffer.get();
|
---|
99 | value |= (v & 0x7f) << 28;
|
---|
100 | if ((v & 0x80) != 0) {
|
---|
101 | v = buffer.get();
|
---|
102 | value |= (v & 0x7f) << 35;
|
---|
103 | if ((v & 0x80) != 0) {
|
---|
104 | v = buffer.get();
|
---|
105 | value |= (v & 0x7f) << 42;
|
---|
106 | if ((v & 0x80) != 0) {
|
---|
107 | v = buffer.get();
|
---|
108 | value |= (v & 0x7f) << 49;
|
---|
109 | if ((v & 0x80) != 0) {
|
---|
110 | v = buffer.get();
|
---|
111 | value |= v << 56;
|
---|
112 | }
|
---|
113 | }
|
---|
114 | }
|
---|
115 | }
|
---|
116 | }
|
---|
117 | }
|
---|
118 | }
|
---|
119 | }
|
---|
120 | value = (value >>> 1) ^ -(value & 1);
|
---|
121 | return value;
|
---|
122 | }
|
---|
123 | }
|
---|
124 |
|
---|
125 | export default ZigZagEncoding;
|
---|