Projekt

Obecné

Profil

Stáhnout (4.77 KB) Statistiky
| Větev: | Revize:
1
"use strict";
2

    
3
Object.defineProperty(exports, "__esModule", {
4
  value: true
5
});
6
exports.alloc = alloc;
7
exports.free = free;
8
exports.resize = resize;
9
exports.readInt = readInt;
10
exports.readUInt = readUInt;
11
exports.writeInt64 = writeInt64;
12
exports.writeUInt64 = writeUInt64;
13
// Copyright 2012 The Obvious Corporation.
14

    
15
/*
16
 * bufs: Buffer utilities.
17
 */
18

    
19
/*
20
 * Module variables
21
 */
22

    
23
/** Pool of buffers, where `bufPool[x].length === x`. */
24
var bufPool = [];
25
/** Maximum length of kept temporary buffers. */
26

    
27
var TEMP_BUF_MAXIMUM_LENGTH = 20;
28
/** Minimum exactly-representable 64-bit int. */
29

    
30
var MIN_EXACT_INT64 = -0x8000000000000000;
31
/** Maximum exactly-representable 64-bit int. */
32

    
33
var MAX_EXACT_INT64 = 0x7ffffffffffffc00;
34
/** Maximum exactly-representable 64-bit uint. */
35

    
36
var MAX_EXACT_UINT64 = 0xfffffffffffff800;
37
/**
38
 * The int value consisting just of a 1 in bit #32 (that is, one more
39
 * than the maximum 32-bit unsigned value).
40
 */
41

    
42
var BIT_32 = 0x100000000;
43
/**
44
 * The int value consisting just of a 1 in bit #64 (that is, one more
45
 * than the maximum 64-bit unsigned value).
46
 */
47

    
48
var BIT_64 = 0x10000000000000000;
49
/*
50
 * Helper functions
51
 */
52

    
53
/**
54
 * Masks off all but the lowest bit set of the given number.
55
 */
56

    
57
function lowestBit(num) {
58
  return num & -num;
59
}
60
/**
61
 * Gets whether trying to add the second number to the first is lossy
62
 * (inexact). The first number is meant to be an accumulated result.
63
 */
64

    
65

    
66
function isLossyToAdd(accum, num) {
67
  if (num === 0) {
68
    return false;
69
  }
70

    
71
  var lowBit = lowestBit(num);
72
  var added = accum + lowBit;
73

    
74
  if (added === accum) {
75
    return true;
76
  }
77

    
78
  if (added - lowBit !== accum) {
79
    return true;
80
  }
81

    
82
  return false;
83
}
84
/*
85
 * Exported functions
86
 */
87

    
88
/**
89
 * Allocates a buffer of the given length, which is initialized
90
 * with all zeroes. This returns a buffer from the pool if it is
91
 * available, or a freshly-allocated buffer if not.
92
 */
93

    
94

    
95
function alloc(length) {
96
  var result = bufPool[length];
97

    
98
  if (result) {
99
    bufPool[length] = undefined;
100
  } else {
101
    result = new Buffer(length);
102
  }
103

    
104
  result.fill(0);
105
  return result;
106
}
107
/**
108
 * Releases a buffer back to the pool.
109
 */
110

    
111

    
112
function free(buffer) {
113
  var length = buffer.length;
114

    
115
  if (length < TEMP_BUF_MAXIMUM_LENGTH) {
116
    bufPool[length] = buffer;
117
  }
118
}
119
/**
120
 * Resizes a buffer, returning a new buffer. Returns the argument if
121
 * the length wouldn't actually change. This function is only safe to
122
 * use if the given buffer was allocated within this module (since
123
 * otherwise the buffer might possibly be shared externally).
124
 */
125

    
126

    
127
function resize(buffer, length) {
128
  if (length === buffer.length) {
129
    return buffer;
130
  }
131

    
132
  var newBuf = alloc(length);
133
  buffer.copy(newBuf);
134
  free(buffer);
135
  return newBuf;
136
}
137
/**
138
 * Reads an arbitrary signed int from a buffer.
139
 */
140

    
141

    
142
function readInt(buffer) {
143
  var length = buffer.length;
144
  var positive = buffer[length - 1] < 0x80;
145
  var result = positive ? 0 : -1;
146
  var lossy = false; // Note: We can't use bit manipulation here, since that stops
147
  // working if the result won't fit in a 32-bit int.
148

    
149
  if (length < 7) {
150
    // Common case which can't possibly be lossy (because the result has
151
    // no more than 48 bits, and loss only happens with 54 or more).
152
    for (var i = length - 1; i >= 0; i--) {
153
      result = result * 0x100 + buffer[i];
154
    }
155
  } else {
156
    for (var _i = length - 1; _i >= 0; _i--) {
157
      var one = buffer[_i];
158
      result *= 0x100;
159

    
160
      if (isLossyToAdd(result, one)) {
161
        lossy = true;
162
      }
163

    
164
      result += one;
165
    }
166
  }
167

    
168
  return {
169
    value: result,
170
    lossy: lossy
171
  };
172
}
173
/**
174
 * Reads an arbitrary unsigned int from a buffer.
175
 */
176

    
177

    
178
function readUInt(buffer) {
179
  var length = buffer.length;
180
  var result = 0;
181
  var lossy = false; // Note: See above in re bit manipulation.
182

    
183
  if (length < 7) {
184
    // Common case which can't possibly be lossy (see above).
185
    for (var i = length - 1; i >= 0; i--) {
186
      result = result * 0x100 + buffer[i];
187
    }
188
  } else {
189
    for (var _i2 = length - 1; _i2 >= 0; _i2--) {
190
      var one = buffer[_i2];
191
      result *= 0x100;
192

    
193
      if (isLossyToAdd(result, one)) {
194
        lossy = true;
195
      }
196

    
197
      result += one;
198
    }
199
  }
200

    
201
  return {
202
    value: result,
203
    lossy: lossy
204
  };
205
}
206
/**
207
 * Writes a little-endian 64-bit signed int into a buffer.
208
 */
209

    
210

    
211
function writeInt64(value, buffer) {
212
  if (value < MIN_EXACT_INT64 || value > MAX_EXACT_INT64) {
213
    throw new Error("Value out of range.");
214
  }
215

    
216
  if (value < 0) {
217
    value += BIT_64;
218
  }
219

    
220
  writeUInt64(value, buffer);
221
}
222
/**
223
 * Writes a little-endian 64-bit unsigned int into a buffer.
224
 */
225

    
226

    
227
function writeUInt64(value, buffer) {
228
  if (value < 0 || value > MAX_EXACT_UINT64) {
229
    throw new Error("Value out of range.");
230
  }
231

    
232
  var lowWord = value % BIT_32;
233
  var highWord = Math.floor(value / BIT_32);
234
  buffer.writeUInt32LE(lowWord, 0);
235
  buffer.writeUInt32LE(highWord, 4);
236
}
(2-2/4)