| 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 |