Projekt

Obecné

Profil

Stáhnout (7.45 KB) Statistiky
| Větev: | Revize:
1
// Copyright 2012 The Obvious Corporation.
2

    
3
/*
4
 * leb: LEB128 utilities.
5
 */
6

    
7
/*
8
 * Modules used
9
 */
10
"use strict";
11

    
12
import Long from "@xtuc/long";
13
import * as bits from "./bits";
14
import * as bufs from "./bufs";
15
/*
16
 * Module variables
17
 */
18

    
19
/** The minimum possible 32-bit signed int. */
20

    
21
var MIN_INT32 = -0x80000000;
22
/** The maximum possible 32-bit signed int. */
23

    
24
var MAX_INT32 = 0x7fffffff;
25
/** The maximum possible 32-bit unsigned int. */
26

    
27
var MAX_UINT32 = 0xffffffff;
28
/** The minimum possible 64-bit signed int. */
29
// const MIN_INT64 = -0x8000000000000000;
30

    
31
/**
32
 * The maximum possible 64-bit signed int that is representable as a
33
 * JavaScript number.
34
 */
35
// const MAX_INT64 = 0x7ffffffffffffc00;
36

    
37
/**
38
 * The maximum possible 64-bit unsigned int that is representable as a
39
 * JavaScript number.
40
 */
41
// const MAX_UINT64 = 0xfffffffffffff800;
42

    
43
/*
44
 * Helper functions
45
 */
46

    
47
/**
48
 * Determines the number of bits required to encode the number
49
 * represented in the given buffer as a signed value. The buffer is
50
 * taken to represent a signed number in little-endian form.
51
 *
52
 * The number of bits to encode is the (zero-based) bit number of the
53
 * highest-order non-sign-matching bit, plus two. For example:
54
 *
55
 *   11111011 01110101
56
 *   high          low
57
 *
58
 * The sign bit here is 1 (that is, it's a negative number). The highest
59
 * bit number that doesn't match the sign is bit #10 (where the lowest-order
60
 * bit is bit #0). So, we have to encode at least 12 bits total.
61
 *
62
 * As a special degenerate case, the numbers 0 and -1 each require just one bit.
63
 */
64

    
65
function signedBitCount(buffer) {
66
  return bits.highOrder(bits.getSign(buffer) ^ 1, buffer) + 2;
67
}
68
/**
69
 * Determines the number of bits required to encode the number
70
 * represented in the given buffer as an unsigned value. The buffer is
71
 * taken to represent an unsigned number in little-endian form.
72
 *
73
 * The number of bits to encode is the (zero-based) bit number of the
74
 * highest-order 1 bit, plus one. For example:
75
 *
76
 *   00011000 01010011
77
 *   high          low
78
 *
79
 * The highest-order 1 bit here is bit #12 (where the lowest-order bit
80
 * is bit #0). So, we have to encode at least 13 bits total.
81
 *
82
 * As a special degenerate case, the number 0 requires 1 bit.
83
 */
84

    
85

    
86
function unsignedBitCount(buffer) {
87
  var result = bits.highOrder(1, buffer) + 1;
88
  return result ? result : 1;
89
}
90
/**
91
 * Common encoder for both signed and unsigned ints. This takes a
92
 * bigint-ish buffer, returning an LEB128-encoded buffer.
93
 */
94

    
95

    
96
function encodeBufferCommon(buffer, signed) {
97
  var signBit;
98
  var bitCount;
99

    
100
  if (signed) {
101
    signBit = bits.getSign(buffer);
102
    bitCount = signedBitCount(buffer);
103
  } else {
104
    signBit = 0;
105
    bitCount = unsignedBitCount(buffer);
106
  }
107

    
108
  var byteCount = Math.ceil(bitCount / 7);
109
  var result = bufs.alloc(byteCount);
110

    
111
  for (var i = 0; i < byteCount; i++) {
112
    var payload = bits.extract(buffer, i * 7, 7, signBit);
113
    result[i] = payload | 0x80;
114
  } // Mask off the top bit of the last byte, to indicate the end of the
115
  // encoding.
116

    
117

    
118
  result[byteCount - 1] &= 0x7f;
119
  return result;
120
}
121
/**
122
 * Gets the byte-length of the value encoded in the given buffer at
123
 * the given index.
124
 */
125

    
126

    
127
function encodedLength(encodedBuffer, index) {
128
  var result = 0;
129

    
130
  while (encodedBuffer[index + result] >= 0x80) {
131
    result++;
132
  }
133

    
134
  result++; // to account for the last byte
135

    
136
  if (index + result > encodedBuffer.length) {// FIXME(sven): seems to cause false positives
137
    // throw new Error("integer representation too long");
138
  }
139

    
140
  return result;
141
}
142
/**
143
 * Common decoder for both signed and unsigned ints. This takes an
144
 * LEB128-encoded buffer, returning a bigint-ish buffer.
145
 */
146

    
147

    
148
function decodeBufferCommon(encodedBuffer, index, signed) {
149
  index = index === undefined ? 0 : index;
150
  var length = encodedLength(encodedBuffer, index);
151
  var bitLength = length * 7;
152
  var byteLength = Math.ceil(bitLength / 8);
153
  var result = bufs.alloc(byteLength);
154
  var outIndex = 0;
155

    
156
  while (length > 0) {
157
    bits.inject(result, outIndex, 7, encodedBuffer[index]);
158
    outIndex += 7;
159
    index++;
160
    length--;
161
  }
162

    
163
  var signBit;
164
  var signByte;
165

    
166
  if (signed) {
167
    // Sign-extend the last byte.
168
    var lastByte = result[byteLength - 1];
169
    var endBit = outIndex % 8;
170

    
171
    if (endBit !== 0) {
172
      var shift = 32 - endBit; // 32 because JS bit ops work on 32-bit ints.
173

    
174
      lastByte = result[byteLength - 1] = lastByte << shift >> shift & 0xff;
175
    }
176

    
177
    signBit = lastByte >> 7;
178
    signByte = signBit * 0xff;
179
  } else {
180
    signBit = 0;
181
    signByte = 0;
182
  } // Slice off any superfluous bytes, that is, ones that add no meaningful
183
  // bits (because the value would be the same if they were removed).
184

    
185

    
186
  while (byteLength > 1 && result[byteLength - 1] === signByte && (!signed || result[byteLength - 2] >> 7 === signBit)) {
187
    byteLength--;
188
  }
189

    
190
  result = bufs.resize(result, byteLength);
191
  return {
192
    value: result,
193
    nextIndex: index
194
  };
195
}
196
/*
197
 * Exported bindings
198
 */
199

    
200

    
201
function encodeIntBuffer(buffer) {
202
  return encodeBufferCommon(buffer, true);
203
}
204

    
205
function decodeIntBuffer(encodedBuffer, index) {
206
  return decodeBufferCommon(encodedBuffer, index, true);
207
}
208

    
209
function encodeInt32(num) {
210
  var buf = bufs.alloc(4);
211
  buf.writeInt32LE(num, 0);
212
  var result = encodeIntBuffer(buf);
213
  bufs.free(buf);
214
  return result;
215
}
216

    
217
function decodeInt32(encodedBuffer, index) {
218
  var result = decodeIntBuffer(encodedBuffer, index);
219
  var parsed = bufs.readInt(result.value);
220
  var value = parsed.value;
221
  bufs.free(result.value);
222

    
223
  if (value < MIN_INT32 || value > MAX_INT32) {
224
    throw new Error("integer too large");
225
  }
226

    
227
  return {
228
    value: value,
229
    nextIndex: result.nextIndex
230
  };
231
}
232

    
233
function encodeInt64(num) {
234
  var buf = bufs.alloc(8);
235
  bufs.writeInt64(num, buf);
236
  var result = encodeIntBuffer(buf);
237
  bufs.free(buf);
238
  return result;
239
}
240

    
241
function decodeInt64(encodedBuffer, index) {
242
  var result = decodeIntBuffer(encodedBuffer, index);
243
  var value = Long.fromBytesLE(result.value, false);
244
  bufs.free(result.value);
245
  return {
246
    value: value,
247
    nextIndex: result.nextIndex,
248
    lossy: false
249
  };
250
}
251

    
252
function encodeUIntBuffer(buffer) {
253
  return encodeBufferCommon(buffer, false);
254
}
255

    
256
function decodeUIntBuffer(encodedBuffer, index) {
257
  return decodeBufferCommon(encodedBuffer, index, false);
258
}
259

    
260
function encodeUInt32(num) {
261
  var buf = bufs.alloc(4);
262
  buf.writeUInt32LE(num, 0);
263
  var result = encodeUIntBuffer(buf);
264
  bufs.free(buf);
265
  return result;
266
}
267

    
268
function decodeUInt32(encodedBuffer, index) {
269
  var result = decodeUIntBuffer(encodedBuffer, index);
270
  var parsed = bufs.readUInt(result.value);
271
  var value = parsed.value;
272
  bufs.free(result.value);
273

    
274
  if (value > MAX_UINT32) {
275
    throw new Error("integer too large");
276
  }
277

    
278
  return {
279
    value: value,
280
    nextIndex: result.nextIndex
281
  };
282
}
283

    
284
function encodeUInt64(num) {
285
  var buf = bufs.alloc(8);
286
  bufs.writeUInt64(num, buf);
287
  var result = encodeUIntBuffer(buf);
288
  bufs.free(buf);
289
  return result;
290
}
291

    
292
function decodeUInt64(encodedBuffer, index) {
293
  var result = decodeUIntBuffer(encodedBuffer, index);
294
  var value = Long.fromBytesLE(result.value, true);
295
  bufs.free(result.value);
296
  return {
297
    value: value,
298
    nextIndex: result.nextIndex,
299
    lossy: false
300
  };
301
}
302

    
303
export default {
304
  decodeInt32: decodeInt32,
305
  decodeInt64: decodeInt64,
306
  decodeIntBuffer: decodeIntBuffer,
307
  decodeUInt32: decodeUInt32,
308
  decodeUInt64: decodeUInt64,
309
  decodeUIntBuffer: decodeUIntBuffer,
310
  encodeInt32: encodeInt32,
311
  encodeInt64: encodeInt64,
312
  encodeIntBuffer: encodeIntBuffer,
313
  encodeUInt32: encodeUInt32,
314
  encodeUInt64: encodeUInt64,
315
  encodeUIntBuffer: encodeUIntBuffer
316
};
(4-4/4)