dataReader.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. 'use strict';
  2. var utils = require('./utils');
  3. function DataReader(data) {
  4. this.data = null; // type : see implementation
  5. this.length = 0;
  6. this.index = 0;
  7. this.zero = 0;
  8. }
  9. DataReader.prototype = {
  10. /**
  11. * Check that the offset will not go too far.
  12. * @param {string} offset the additional offset to check.
  13. * @throws {Error} an Error if the offset is out of bounds.
  14. */
  15. checkOffset: function(offset) {
  16. this.checkIndex(this.index + offset);
  17. },
  18. /**
  19. * Check that the specifed index will not be too far.
  20. * @param {string} newIndex the index to check.
  21. * @throws {Error} an Error if the index is out of bounds.
  22. */
  23. checkIndex: function(newIndex) {
  24. if (this.length < this.zero + newIndex || newIndex < 0) {
  25. throw new Error("End of data reached (data length = " + this.length + ", asked index = " + (newIndex) + "). Corrupted zip ?");
  26. }
  27. },
  28. /**
  29. * Change the index.
  30. * @param {number} newIndex The new index.
  31. * @throws {Error} if the new index is out of the data.
  32. */
  33. setIndex: function(newIndex) {
  34. this.checkIndex(newIndex);
  35. this.index = newIndex;
  36. },
  37. /**
  38. * Skip the next n bytes.
  39. * @param {number} n the number of bytes to skip.
  40. * @throws {Error} if the new index is out of the data.
  41. */
  42. skip: function(n) {
  43. this.setIndex(this.index + n);
  44. },
  45. /**
  46. * Get the byte at the specified index.
  47. * @param {number} i the index to use.
  48. * @return {number} a byte.
  49. */
  50. byteAt: function(i) {
  51. // see implementations
  52. },
  53. /**
  54. * Get the next number with a given byte size.
  55. * @param {number} size the number of bytes to read.
  56. * @return {number} the corresponding number.
  57. */
  58. readInt: function(size) {
  59. var result = 0,
  60. i;
  61. this.checkOffset(size);
  62. for (i = this.index + size - 1; i >= this.index; i--) {
  63. result = (result << 8) + this.byteAt(i);
  64. }
  65. this.index += size;
  66. return result;
  67. },
  68. /**
  69. * Get the next string with a given byte size.
  70. * @param {number} size the number of bytes to read.
  71. * @return {string} the corresponding string.
  72. */
  73. readString: function(size) {
  74. return utils.transformTo("string", this.readData(size));
  75. },
  76. /**
  77. * Get raw data without conversion, <size> bytes.
  78. * @param {number} size the number of bytes to read.
  79. * @return {Object} the raw data, implementation specific.
  80. */
  81. readData: function(size) {
  82. // see implementations
  83. },
  84. /**
  85. * Find the last occurence of a zip signature (4 bytes).
  86. * @param {string} sig the signature to find.
  87. * @return {number} the index of the last occurence, -1 if not found.
  88. */
  89. lastIndexOfSignature: function(sig) {
  90. // see implementations
  91. },
  92. /**
  93. * Get the next date.
  94. * @return {Date} the date.
  95. */
  96. readDate: function() {
  97. var dostime = this.readInt(4);
  98. return new Date(
  99. ((dostime >> 25) & 0x7f) + 1980, // year
  100. ((dostime >> 21) & 0x0f) - 1, // month
  101. (dostime >> 16) & 0x1f, // day
  102. (dostime >> 11) & 0x1f, // hour
  103. (dostime >> 5) & 0x3f, // minute
  104. (dostime & 0x1f) << 1); // second
  105. }
  106. };
  107. module.exports = DataReader;