DataReader.jsm 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /* -*- Mode: js; js-indent-level: 2; indent-tabs-mode: nil; tab-width: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  4. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. /* jshint esnext: true, moz: true */
  6. 'use strict';
  7. this.EXPORTED_SYMBOLS = ['DataReader'];
  8. class DataReader {
  9. // `data` is `Uint8Array`
  10. constructor(data, startByte = 0) {
  11. this._data = data;
  12. this._cursor = startByte;
  13. }
  14. get buffer() {
  15. return this._data.buffer;
  16. }
  17. get data() {
  18. return this._data;
  19. }
  20. get eof() {
  21. return this._cursor >= this._data.length;
  22. }
  23. getBytes(length = 1) {
  24. if (!length) {
  25. return new Uint8Array();
  26. }
  27. let end = this._cursor + length;
  28. if (end > this._data.length) {
  29. return new Uint8Array();
  30. }
  31. let uint8Array = new Uint8Array(this.buffer.slice(this._cursor, end));
  32. this._cursor += length;
  33. return uint8Array;
  34. }
  35. getString(length) {
  36. let uint8Array = this.getBytes(length);
  37. return _uint8ArrayToString(uint8Array);
  38. }
  39. getValue(length) {
  40. let uint8Array = this.getBytes(length);
  41. return _uint8ArrayToValue(uint8Array);
  42. }
  43. getLabel(decompressData) {
  44. let parts = [];
  45. let partLength;
  46. while ((partLength = this.getValue(1))) {
  47. // If a length has been specified instead of a pointer,
  48. // read the string of the specified length.
  49. if (partLength !== 0xc0) {
  50. parts.push(this.getString(partLength));
  51. continue;
  52. }
  53. // TODO: Handle case where we have a pointer to the label
  54. parts.push(String.fromCharCode(0xc0) + this.getString(1));
  55. break;
  56. }
  57. let label = parts.join('.');
  58. return _decompressLabel(label, decompressData || this._data);
  59. }
  60. }
  61. /**
  62. * @private
  63. */
  64. function _uint8ArrayToValue(uint8Array) {
  65. let length = uint8Array.length;
  66. if (length === 0) {
  67. return null;
  68. }
  69. let value = 0;
  70. for (let i = 0; i < length; i++) {
  71. value = value << 8;
  72. value += uint8Array[i];
  73. }
  74. return value;
  75. }
  76. /**
  77. * @private
  78. */
  79. function _uint8ArrayToString(uint8Array) {
  80. let length = uint8Array.length;
  81. if (length === 0) {
  82. return '';
  83. }
  84. let results = [];
  85. for (let i = 0; i < length; i += 1024) {
  86. results.push(String.fromCharCode.apply(null, uint8Array.subarray(i, i + 1024)));
  87. }
  88. return results.join('');
  89. }
  90. /**
  91. * @private
  92. */
  93. function _decompressLabel(label, decompressData) {
  94. let result = '';
  95. for (let i = 0, length = label.length; i < length; i++) {
  96. if (label.charCodeAt(i) !== 0xc0) {
  97. result += label.charAt(i);
  98. continue;
  99. }
  100. i++;
  101. let reader = new DataReader(decompressData, label.charCodeAt(i));
  102. result += _decompressLabel(reader.getLabel(), decompressData);
  103. }
  104. return result;
  105. }