OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 function ByteReader(arrayBuffer, opt_offset, opt_length) { | 5 function ByteReader(arrayBuffer, opt_offset, opt_length) { |
6 opt_offset = opt_offset || 0; | 6 opt_offset = opt_offset || 0; |
7 opt_length = opt_length || (arrayBuffer.byteLength - opt_offset); | 7 opt_length = opt_length || (arrayBuffer.byteLength - opt_offset); |
8 this.view_ = new DataView(arrayBuffer, opt_offset, opt_length); | 8 this.view_ = new DataView(arrayBuffer, opt_offset, opt_length); |
9 this.pos_ = 0; | 9 this.pos_ = 0; |
10 this.seekStack_ = []; | 10 this.seekStack_ = []; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 | 56 |
57 if (pos + size > end) | 57 if (pos + size > end) |
58 throw new Error('Read past end of buffer'); | 58 throw new Error('Read past end of buffer'); |
59 }; | 59 }; |
60 | 60 |
61 /** | 61 /** |
62 * Read as a sequence of characters, returning them as a single string. | 62 * Read as a sequence of characters, returning them as a single string. |
63 * | 63 * |
64 * This is a static utility function. There is a member function with the | 64 * This is a static utility function. There is a member function with the |
65 * same name which side-effects the current read position. | 65 * same name which side-effects the current read position. |
| 66 * @return {string} //TODO(JSDOC). |
66 */ | 67 */ |
67 ByteReader.readString = function(dataView, pos, size, opt_end) { | 68 ByteReader.readString = function(dataView, pos, size, opt_end) { |
68 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); | 69 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); |
69 | 70 |
70 var codes = []; | 71 var codes = []; |
71 | 72 |
72 for (var i = 0; i < size; ++i) | 73 for (var i = 0; i < size; ++i) |
73 codes.push(dataView.getUint8(pos + i)); | 74 codes.push(dataView.getUint8(pos + i)); |
74 | 75 |
75 return String.fromCharCode.apply(null, codes); | 76 return String.fromCharCode.apply(null, codes); |
76 }; | 77 }; |
77 | 78 |
78 /** | 79 /** |
79 * Read as a sequence of characters, returning them as a single string. | 80 * Read as a sequence of characters, returning them as a single string. |
80 * | 81 * |
81 * This is a static utility function. There is a member function with the | 82 * This is a static utility function. There is a member function with the |
82 * same name which side-effects the current read position. | 83 * same name which side-effects the current read position. |
| 84 * @return {string} //TODO(JSDOC). |
83 */ | 85 */ |
84 ByteReader.readNullTerminatedString = function(dataView, pos, size, opt_end) { | 86 ByteReader.readNullTerminatedString = function(dataView, pos, size, opt_end) { |
85 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); | 87 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); |
86 | 88 |
87 var codes = []; | 89 var codes = []; |
88 | 90 |
89 for (var i = 0; i < size; ++i) { | 91 for (var i = 0; i < size; ++i) { |
90 var code = dataView.getUint8(pos + i); | 92 var code = dataView.getUint8(pos + i); |
91 if (code == 0) break; | 93 if (code == 0) break; |
92 codes.push(code); | 94 codes.push(code); |
93 } | 95 } |
94 | 96 |
95 return String.fromCharCode.apply(null, codes); | 97 return String.fromCharCode.apply(null, codes); |
96 }; | 98 }; |
97 | 99 |
98 /** | 100 /** |
99 * Read as a sequence of UTF16 characters, returning them as a single string. | 101 * Read as a sequence of UTF16 characters, returning them as a single string. |
100 * | 102 * |
101 * This is a static utility function. There is a member function with the | 103 * This is a static utility function. There is a member function with the |
102 * same name which side-effects the current read position. | 104 * same name which side-effects the current read position. |
| 105 * @return {string} //TODO(JSDOC). |
103 */ | 106 */ |
104 ByteReader.readNullTerminatedStringUTF16 = function( | 107 ByteReader.readNullTerminatedStringUTF16 = function( |
105 dataView, pos, bom, size, opt_end) { | 108 dataView, pos, bom, size, opt_end) { |
106 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); | 109 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); |
107 | 110 |
108 var littleEndian = false; | 111 var littleEndian = false; |
109 var start = 0; | 112 var start = 0; |
110 | 113 |
111 if (bom) { | 114 if (bom) { |
112 littleEndian = (dataView.getUint8(pos) == 0xFF); | 115 littleEndian = (dataView.getUint8(pos) == 0xFF); |
(...skipping 19 matching lines...) Expand all Loading... |
132 ByteReader.base64Alphabet_ = | 135 ByteReader.base64Alphabet_ = |
133 ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'). | 136 ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'). |
134 split(''); | 137 split(''); |
135 | 138 |
136 /** | 139 /** |
137 * Read as a sequence of bytes, returning them as a single base64 encoded | 140 * Read as a sequence of bytes, returning them as a single base64 encoded |
138 * string. | 141 * string. |
139 * | 142 * |
140 * This is a static utility function. There is a member function with the | 143 * This is a static utility function. There is a member function with the |
141 * same name which side-effects the current read position. | 144 * same name which side-effects the current read position. |
| 145 * @return {string} //TODO(JSDOC). |
142 */ | 146 */ |
143 ByteReader.readBase64 = function(dataView, pos, size, opt_end) { | 147 ByteReader.readBase64 = function(dataView, pos, size, opt_end) { |
144 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); | 148 ByteReader.validateRead(pos, size, opt_end || dataView.byteLength); |
145 | 149 |
146 var rv = []; | 150 var rv = []; |
147 var chars = []; | 151 var chars = []; |
148 var padding = 0; | 152 var padding = 0; |
149 | 153 |
150 for (var i = 0; i < size; /* incremented inside */) { | 154 for (var i = 0; i < size; /* incremented inside */) { |
151 var bits = dataView.getUint8(pos + (i++)) << 16; | 155 var bits = dataView.getUint8(pos + (i++)) << 16; |
(...skipping 24 matching lines...) Expand all Loading... |
176 rv[rv.length - 2] = '='; | 180 rv[rv.length - 2] = '='; |
177 | 181 |
178 return rv.join(''); | 182 return rv.join(''); |
179 }; | 183 }; |
180 | 184 |
181 /** | 185 /** |
182 * Read as an image encoded in a data url. | 186 * Read as an image encoded in a data url. |
183 * | 187 * |
184 * This is a static utility function. There is a member function with the | 188 * This is a static utility function. There is a member function with the |
185 * same name which side-effects the current read position. | 189 * same name which side-effects the current read position. |
| 190 * @return {string} //TODO(JSDOC). |
186 */ | 191 */ |
187 ByteReader.readImage = function(dataView, pos, size, opt_end) { | 192 ByteReader.readImage = function(dataView, pos, size, opt_end) { |
188 opt_end = opt_end || dataView.byteLength; | 193 opt_end = opt_end || dataView.byteLength; |
189 ByteReader.validateRead(pos, size, opt_end); | 194 ByteReader.validateRead(pos, size, opt_end); |
190 | 195 |
191 // Two bytes is enough to identify the mime type. | 196 // Two bytes is enough to identify the mime type. |
192 var prefixToMime = { | 197 var prefixToMime = { |
193 '\x89P' : 'png', | 198 '\x89P' : 'png', |
194 '\xFF\xD8' : 'jpeg', | 199 '\xFF\xD8' : 'jpeg', |
195 'BM' : 'bmp', | 200 'BM' : 'bmp', |
196 'GI' : 'gif' | 201 'GI' : 'gif' |
197 }; | 202 }; |
198 | 203 |
199 var prefix = ByteReader.readString(dataView, pos, 2, opt_end); | 204 var prefix = ByteReader.readString(dataView, pos, 2, opt_end); |
200 var mime = prefixToMime[prefix] || | 205 var mime = prefixToMime[prefix] || |
201 dataView.getUint16(pos, false).toString(16); // For debugging. | 206 dataView.getUint16(pos, false).toString(16); // For debugging. |
202 | 207 |
203 var b64 = ByteReader.readBase64(dataView, pos, size, opt_end); | 208 var b64 = ByteReader.readBase64(dataView, pos, size, opt_end); |
204 return 'data:image/' + mime + ';base64,' + b64; | 209 return 'data:image/' + mime + ';base64,' + b64; |
205 }; | 210 }; |
206 | 211 |
207 // Instance methods. | 212 // Instance methods. |
208 | 213 |
209 /** | 214 /** |
210 * Return true if the requested number of bytes can be read from the buffer. | 215 * Return true if the requested number of bytes can be read from the buffer. |
| 216 * @return {boolean} //TODO(JSDOC). |
211 */ | 217 */ |
212 ByteReader.prototype.canRead = function(size) { | 218 ByteReader.prototype.canRead = function(size) { |
213 return this.pos_ + size <= this.view_.byteLength; | 219 return this.pos_ + size <= this.view_.byteLength; |
214 }; | 220 }; |
215 | 221 |
216 /** | 222 /** |
217 * Return true if the current position is past the end of the buffer. | 223 * Return true if the current position is past the end of the buffer. |
| 224 * @return {boolean} //TODO(JSDOC). |
218 */ | 225 */ |
219 ByteReader.prototype.eof = function() { | 226 ByteReader.prototype.eof = function() { |
220 return this.pos_ >= this.view_.byteLength; | 227 return this.pos_ >= this.view_.byteLength; |
221 }; | 228 }; |
222 | 229 |
223 /** | 230 /** |
224 * Return true if the current position is before the beginning of the buffer. | 231 * Return true if the current position is before the beginning of the buffer. |
| 232 * @return {boolean} //TODO(JSDOC). |
225 */ | 233 */ |
226 ByteReader.prototype.bof = function() { | 234 ByteReader.prototype.bof = function() { |
227 return this.pos_ < 0; | 235 return this.pos_ < 0; |
228 }; | 236 }; |
229 | 237 |
230 /** | 238 /** |
231 * Return true if the current position is outside the buffer. | 239 * Return true if the current position is outside the buffer. |
| 240 * @return {boolean} //TODO(JSDOC). |
232 */ | 241 */ |
233 ByteReader.prototype.beof = function() { | 242 ByteReader.prototype.beof = function() { |
234 return this.pos_ >= this.view_.byteLength || this.pos_ < 0; | 243 return this.pos_ >= this.view_.byteLength || this.pos_ < 0; |
235 }; | 244 }; |
236 | 245 |
237 /** | 246 /** |
238 * Set the expected byte ordering for future reads. | 247 * Set the expected byte ordering for future reads. |
239 */ | 248 */ |
240 ByteReader.prototype.setByteOrder = function(order) { | 249 ByteReader.prototype.setByteOrder = function(order) { |
241 this.littleEndian_ = order == ByteReader.LITTLE_ENDIAN; | 250 this.littleEndian_ = order == ByteReader.LITTLE_ENDIAN; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 var rv = this.view_[method](this.pos_, this.littleEndian_); | 299 var rv = this.view_[method](this.pos_, this.littleEndian_); |
291 this.pos_ += width; | 300 this.pos_ += width; |
292 return rv; | 301 return rv; |
293 }; | 302 }; |
294 | 303 |
295 /** | 304 /** |
296 * Read as a sequence of characters, returning them as a single string. | 305 * Read as a sequence of characters, returning them as a single string. |
297 * | 306 * |
298 * Adjusts the current position on success. Throws an exception if the | 307 * Adjusts the current position on success. Throws an exception if the |
299 * read would go past the end of the buffer. | 308 * read would go past the end of the buffer. |
| 309 * @return {string} //TODO(JSDOC). |
300 */ | 310 */ |
301 ByteReader.prototype.readString = function(size, opt_end) { | 311 ByteReader.prototype.readString = function(size, opt_end) { |
302 var rv = ByteReader.readString(this.view_, this.pos_, size, opt_end); | 312 var rv = ByteReader.readString(this.view_, this.pos_, size, opt_end); |
303 this.pos_ += size; | 313 this.pos_ += size; |
304 return rv; | 314 return rv; |
305 }; | 315 }; |
306 | 316 |
307 | 317 |
308 /** | 318 /** |
309 * Read as a sequence of characters, returning them as a single string. | 319 * Read as a sequence of characters, returning them as a single string. |
310 * | 320 * |
311 * Adjusts the current position on success. Throws an exception if the | 321 * Adjusts the current position on success. Throws an exception if the |
312 * read would go past the end of the buffer. | 322 * read would go past the end of the buffer. |
| 323 * @return {string} //TODO(JSDOC). |
313 */ | 324 */ |
314 ByteReader.prototype.readNullTerminatedString = function(size, opt_end) { | 325 ByteReader.prototype.readNullTerminatedString = function(size, opt_end) { |
315 var rv = ByteReader.readNullTerminatedString(this.view_, | 326 var rv = ByteReader.readNullTerminatedString(this.view_, |
316 this.pos_, | 327 this.pos_, |
317 size, | 328 size, |
318 opt_end); | 329 opt_end); |
319 this.pos_ += rv.length; | 330 this.pos_ += rv.length; |
320 | 331 |
321 if (rv.length < size) { | 332 if (rv.length < size) { |
322 // If we've stopped reading because we found '0' but didn't hit size limit | 333 // If we've stopped reading because we found '0' but didn't hit size limit |
323 // then we should skip additional '0' character | 334 // then we should skip additional '0' character |
324 this.pos_++; | 335 this.pos_++; |
325 } | 336 } |
326 | 337 |
327 return rv; | 338 return rv; |
328 }; | 339 }; |
329 | 340 |
330 | 341 |
331 /** | 342 /** |
332 * Read as a sequence of UTF16 characters, returning them as a single string. | 343 * Read as a sequence of UTF16 characters, returning them as a single string. |
333 * | 344 * |
334 * Adjusts the current position on success. Throws an exception if the | 345 * Adjusts the current position on success. Throws an exception if the |
335 * read would go past the end of the buffer. | 346 * read would go past the end of the buffer. |
| 347 * @return {string} //TODO(JSDOC). |
336 */ | 348 */ |
337 ByteReader.prototype.readNullTerminatedStringUTF16 = | 349 ByteReader.prototype.readNullTerminatedStringUTF16 = |
338 function(bom, size, opt_end) { | 350 function(bom, size, opt_end) { |
339 var rv = ByteReader.readNullTerminatedStringUTF16( | 351 var rv = ByteReader.readNullTerminatedStringUTF16( |
340 this.view_, this.pos_, bom, size, opt_end); | 352 this.view_, this.pos_, bom, size, opt_end); |
341 | 353 |
342 if (bom) { | 354 if (bom) { |
343 // If the BOM word was present advance the position. | 355 // If the BOM word was present advance the position. |
344 this.pos_ += 2; | 356 this.pos_ += 2; |
345 } | 357 } |
346 | 358 |
347 this.pos_ += rv.length; | 359 this.pos_ += rv.length; |
348 | 360 |
349 if (rv.length < size) { | 361 if (rv.length < size) { |
350 // If we've stopped reading because we found '0' but didn't hit size limit | 362 // If we've stopped reading because we found '0' but didn't hit size limit |
351 // then we should skip additional '0' character | 363 // then we should skip additional '0' character |
352 this.pos_ += 2; | 364 this.pos_ += 2; |
353 } | 365 } |
354 | 366 |
355 return rv; | 367 return rv; |
356 }; | 368 }; |
357 | 369 |
358 | 370 |
359 /** | 371 /** |
360 * Read as an array of numbers. | 372 * Read as an array of numbers. |
361 * | 373 * |
362 * Adjusts the current position on success. Throws an exception if the | 374 * Adjusts the current position on success. Throws an exception if the |
363 * read would go past the end of the buffer. | 375 * read would go past the end of the buffer. |
| 376 * @return {Array.<*>} //TODO(JSDOC). |
364 */ | 377 */ |
365 ByteReader.prototype.readSlice = function(size, opt_end, | 378 ByteReader.prototype.readSlice = function(size, opt_end, |
366 opt_arrayConstructor) { | 379 opt_arrayConstructor) { |
367 this.validateRead(size, opt_end); | 380 this.validateRead(size, opt_end); |
368 | 381 |
369 var arrayConstructor = opt_arrayConstructor || Uint8Array; | 382 var arrayConstructor = opt_arrayConstructor || Uint8Array; |
370 var slice = new arrayConstructor( | 383 var slice = new arrayConstructor( |
371 this.view_.buffer, this.view_.byteOffset + this.pos, size); | 384 this.view_.buffer, this.view_.byteOffset + this.pos, size); |
372 this.pos_ += size; | 385 this.pos_ += size; |
373 | 386 |
374 return slice; | 387 return slice; |
375 }; | 388 }; |
376 | 389 |
377 /** | 390 /** |
378 * Read as a sequence of bytes, returning them as a single base64 encoded | 391 * Read as a sequence of bytes, returning them as a single base64 encoded |
379 * string. | 392 * string. |
380 * | 393 * |
381 * Adjusts the current position on success. Throws an exception if the | 394 * Adjusts the current position on success. Throws an exception if the |
382 * read would go past the end of the buffer. | 395 * read would go past the end of the buffer. |
| 396 * @return {string} //TODO(JSDOC). |
383 */ | 397 */ |
384 ByteReader.prototype.readBase64 = function(size, opt_end) { | 398 ByteReader.prototype.readBase64 = function(size, opt_end) { |
385 var rv = ByteReader.readBase64(this.view_, this.pos_, size, opt_end); | 399 var rv = ByteReader.readBase64(this.view_, this.pos_, size, opt_end); |
386 this.pos_ += size; | 400 this.pos_ += size; |
387 return rv; | 401 return rv; |
388 }; | 402 }; |
389 | 403 |
390 /** | 404 /** |
391 * Read an image returning it as a data url. | 405 * Read an image returning it as a data url. |
392 * | 406 * |
393 * Adjusts the current position on success. Throws an exception if the | 407 * Adjusts the current position on success. Throws an exception if the |
394 * read would go past the end of the buffer. | 408 * read would go past the end of the buffer. |
| 409 * @return {string} //TODO(JSDOC). |
395 */ | 410 */ |
396 ByteReader.prototype.readImage = function(size, opt_end) { | 411 ByteReader.prototype.readImage = function(size, opt_end) { |
397 var rv = ByteReader.readImage(this.view_, this.pos_, size, opt_end); | 412 var rv = ByteReader.readImage(this.view_, this.pos_, size, opt_end); |
398 this.pos_ += size; | 413 this.pos_ += size; |
399 return rv; | 414 return rv; |
400 }; | 415 }; |
401 | 416 |
402 /** | 417 /** |
403 * Seek to a give position relative to opt_seekStart. | 418 * Seek to a give position relative to opt_seekStart. |
404 */ | 419 */ |
(...skipping 30 matching lines...) Expand all Loading... |
435 | 450 |
436 /** | 451 /** |
437 * Undo a previous seekPush. | 452 * Undo a previous seekPush. |
438 */ | 453 */ |
439 ByteReader.prototype.popSeek = function() { | 454 ByteReader.prototype.popSeek = function() { |
440 this.seek(this.seekStack_.pop()); | 455 this.seek(this.seekStack_.pop()); |
441 }; | 456 }; |
442 | 457 |
443 /** | 458 /** |
444 * Return the current read position. | 459 * Return the current read position. |
| 460 * @return {number} //TODO(JSDOC). |
445 */ | 461 */ |
446 ByteReader.prototype.tell = function() { | 462 ByteReader.prototype.tell = function() { |
447 return this.pos_; | 463 return this.pos_; |
448 }; | 464 }; |
OLD | NEW |