1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5define("mojo/public/js/bindings/buffer", function() {
6
7  var kHostIsLittleEndian = (function () {
8    var endianArrayBuffer = new ArrayBuffer(2);
9    var endianUint8Array = new Uint8Array(endianArrayBuffer);
10    var endianUint16Array = new Uint16Array(endianArrayBuffer);
11    endianUint16Array[0] = 1;
12    return endianUint8Array[0] == 1;
13  })();
14
15  var kHighWordMultiplier = 0x100000000;
16
17  function Buffer(sizeOrArrayBuffer) {
18    if (sizeOrArrayBuffer instanceof ArrayBuffer)
19      this.arrayBuffer = sizeOrArrayBuffer;
20    else
21      this.arrayBuffer = new ArrayBuffer(sizeOrArrayBuffer);
22
23    this.dataView = new DataView(this.arrayBuffer);
24    this.next = 0;
25  }
26
27  Object.defineProperty(Buffer.prototype, "byteLength", {
28    get: function() { return this.arrayBuffer.byteLength; }
29  });
30
31  Buffer.prototype.alloc = function(size) {
32    var pointer = this.next;
33    this.next += size;
34    if (this.next > this.byteLength) {
35      var newSize = (1.5 * (this.byteLength + size)) | 0;
36      this.grow(newSize);
37    }
38    return pointer;
39  };
40
41  function copyArrayBuffer(dstArrayBuffer, srcArrayBuffer) {
42    (new Uint8Array(dstArrayBuffer)).set(new Uint8Array(srcArrayBuffer));
43  }
44
45  Buffer.prototype.grow = function(size) {
46    var newArrayBuffer = new ArrayBuffer(size);
47    copyArrayBuffer(newArrayBuffer, this.arrayBuffer);
48    this.arrayBuffer = newArrayBuffer;
49    this.dataView = new DataView(this.arrayBuffer);
50  };
51
52  Buffer.prototype.trim = function() {
53    this.arrayBuffer = this.arrayBuffer.slice(0, this.next);
54    this.dataView = new DataView(this.arrayBuffer);
55  };
56
57  Buffer.prototype.getUint8 = function(offset) {
58    return this.dataView.getUint8(offset);
59  }
60  Buffer.prototype.getUint16 = function(offset) {
61    return this.dataView.getUint16(offset, kHostIsLittleEndian);
62  }
63  Buffer.prototype.getUint32 = function(offset) {
64    return this.dataView.getUint32(offset, kHostIsLittleEndian);
65  }
66  Buffer.prototype.getUint64 = function(offset) {
67    var lo, hi;
68    if (kHostIsLittleEndian) {
69      lo = this.dataView.getUint32(offset, kHostIsLittleEndian);
70      hi = this.dataView.getUint32(offset + 4, kHostIsLittleEndian);
71    } else {
72      hi = this.dataView.getUint32(offset, kHostIsLittleEndian);
73      lo = this.dataView.getUint32(offset + 4, kHostIsLittleEndian);
74    }
75    return lo + hi * kHighWordMultiplier;
76  }
77
78  Buffer.prototype.getInt8 = function(offset) {
79    return this.dataView.getInt8(offset);
80  }
81  Buffer.prototype.getInt16 = function(offset) {
82    return this.dataView.getInt16(offset, kHostIsLittleEndian);
83  }
84  Buffer.prototype.getInt32 = function(offset) {
85    return this.dataView.getInt32(offset, kHostIsLittleEndian);
86  }
87  Buffer.prototype.getInt64 = function(offset) {
88    var lo, hi;
89    if (kHostIsLittleEndian) {
90      lo = this.dataView.getUint32(offset, kHostIsLittleEndian);
91      hi = this.dataView.getInt32(offset + 4, kHostIsLittleEndian);
92    } else {
93      hi = this.dataView.getInt32(offset, kHostIsLittleEndian);
94      lo = this.dataView.getUint32(offset + 4, kHostIsLittleEndian);
95    }
96    return lo + hi * kHighWordMultiplier;
97  }
98
99  Buffer.prototype.getFloat32 = function(offset) {
100    return this.dataView.getFloat32(offset, kHostIsLittleEndian);
101  }
102  Buffer.prototype.getFloat64 = function(offset) {
103    return this.dataView.getFloat64(offset, kHostIsLittleEndian);
104  }
105
106  Buffer.prototype.setUint8 = function(offset, value) {
107    this.dataView.setUint8(offset, value);
108  }
109  Buffer.prototype.setUint16 = function(offset, value) {
110    this.dataView.setUint16(offset, value, kHostIsLittleEndian);
111  }
112  Buffer.prototype.setUint32 = function(offset, value) {
113    this.dataView.setUint32(offset, value, kHostIsLittleEndian);
114  }
115  Buffer.prototype.setUint64 = function(offset, value) {
116    var hi = (value / kHighWordMultiplier) | 0;
117    if (kHostIsLittleEndian) {
118      this.dataView.setInt32(offset, value, kHostIsLittleEndian);
119      this.dataView.setInt32(offset + 4, hi, kHostIsLittleEndian);
120    } else {
121      this.dataView.setInt32(offset, hi, kHostIsLittleEndian);
122      this.dataView.setInt32(offset + 4, value, kHostIsLittleEndian);
123    }
124  }
125
126  Buffer.prototype.setInt8 = function(offset, value) {
127    this.dataView.setInt8(offset, value);
128  }
129  Buffer.prototype.setInt16 = function(offset, value) {
130    this.dataView.setInt16(offset, value, kHostIsLittleEndian);
131  }
132  Buffer.prototype.setInt32 = function(offset, value) {
133    this.dataView.setInt32(offset, value, kHostIsLittleEndian);
134  }
135  Buffer.prototype.setInt64 = function(offset, value) {
136    var hi = Math.floor(value / kHighWordMultiplier);
137    if (kHostIsLittleEndian) {
138      this.dataView.setInt32(offset, value, kHostIsLittleEndian);
139      this.dataView.setInt32(offset + 4, hi, kHostIsLittleEndian);
140    } else {
141      this.dataView.setInt32(offset, hi, kHostIsLittleEndian);
142      this.dataView.setInt32(offset + 4, value, kHostIsLittleEndian);
143    }
144  }
145
146  Buffer.prototype.setFloat32 = function(offset, value) {
147    this.dataView.setFloat32(offset, value, kHostIsLittleEndian);
148  }
149  Buffer.prototype.setFloat64 = function(offset, value) {
150    this.dataView.setFloat64(offset, value, kHostIsLittleEndian);
151  }
152
153  var exports = {};
154  exports.Buffer = Buffer;
155  return exports;
156});
157