Guest User

Untitled

a guest
Jan 20th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.83 KB | None | 0 0
  1. #!/usr/local/bin/node --max_old_space_size=1024
  2. "use strict";
  3.  
  4. const fs = require('fs');
  5.  
  6. /* eslint-disable */
  7.  
  8. class StreamBuffer {
  9. constructor() {
  10. this.blocks = [];
  11. this.blockSize = 256 * 1024;
  12. this.count = 0;
  13. this.lastBlockLength = 0;
  14. }
  15.  
  16. get length() {
  17. return this.blocks.length === 0
  18. ? 0
  19. : (this.blocks.length - 1) * this.blockSize + this.lastBlockLength;
  20. }
  21.  
  22. set length(value) {
  23. if (value < 0) throw new Error;
  24. this.blocks.length = Math.ceil(value / this.blockSize);
  25.  
  26. for (let index = 0; index < this.blocks.length; ++index)
  27. if (!this.blocks[index])
  28. this.blocks[index] = new Buffer(this.blockSize);
  29.  
  30. this.lastBlockLength = ((value - 1) % this.blockSize) + 1;
  31. }
  32.  
  33. write(buffer, offset = 0, length = buffer.length) {
  34. if (!buffer) throw new Error("Write request a Buffer as first parameter");
  35. if (offset + length > buffer.length) throw new Error("Write buffer params out of index");
  36. var bufferStart = offset, start = this.length, howMany, partToWrite, toBreak;
  37. this.length += length;
  38. while (true) {
  39. howMany = this.blockSize - this.offsetWithinBlock(start);
  40. if (howMany >= length - bufferStart) {
  41. howMany = length - bufferStart;
  42. toBreak = true;
  43. }
  44. partToWrite = buffer.slice(offset, offset + length);
  45. this.writeBlock(this.blockIndexByByteOffset(start), this.offsetWithinBlock(start), partToWrite);
  46. if (toBreak) break;
  47. bufferStart += howMany;
  48. start += howMany;
  49. }
  50. return this;
  51. }
  52.  
  53. writeBlock(blockIndex, offset, buffer) {
  54. var block;
  55. block = this.blocks[blockIndex];
  56. return buffer.copy(block, offset);
  57. }
  58.  
  59. offsetWithinBlock(index) {
  60. return index % this.blockSize;
  61. }
  62.  
  63. blockIndexByByteOffset(index) {
  64. return Math.floor(index / this.blockSize);
  65. }
  66.  
  67. slice(start, end) {
  68. if (start > end) throw new Error("start should less than end")
  69. if (end > this.length) throw new Error("Index out of range");
  70. if (start < 0 || end <= 0) throw new Error("Invalid Offset or Index");
  71. var block, buffer, buffers = [], howMany, length = end - start;
  72. while (start < end) {
  73. howMany = this.blockSize - this.offsetWithinBlock(start);
  74. if (howMany > end - start) howMany = end - start;
  75. block = this.blocks[this.blockIndexByByteOffset(start)];
  76. buffer = block.slice(this.offsetWithinBlock(start), this.offsetWithinBlock(start) + howMany);
  77. buffers.push(buffer);
  78. start += howMany;
  79. }
  80. return Buffer.concat(buffers, length);
  81. }
  82.  
  83. byteAt(index) {
  84. if (index >= this.length) throw new Error("Index Error");
  85. let blockIndex = Math.floor(index / this.blockSize);
  86. if (blockIndex >= this.blocks.length) throw new Error("Range Error");
  87. let block = this.blocks[blockIndex];
  88. let tailIndex = index % this.blockSize;
  89. return block[tailIndex];
  90. }
  91.  
  92. static getStream(path) {
  93. return typeof path.read === 'function'
  94. ? path
  95. : typeof path === 'string' || path instanceof String
  96. ? fs.createReadStream(path)
  97. : null
  98. }
  99.  
  100. static fromFile(path) {
  101. return new Promise((resolve, reject) => {
  102. try {
  103. resolve(this.fromFileSync(path))
  104. } catch (e) {
  105. reject(e);
  106. }
  107. });
  108. }
  109.  
  110. static fromFileSync(path) {
  111. let KB = 1024,
  112. bb = new StreamBuffer(),
  113. readStream = StreamBuffer.getStream(path),
  114. fd = readStream.fd,
  115. buffer = new Buffer(bb.blockSize),
  116. total = 0,
  117. mayBeTotal = 0,
  118. howManyRead, oldLength;
  119.  
  120. while (true) {
  121. try {
  122. howManyRead = fs.readSync(fd, buffer, 0, buffer.length, null);
  123. } catch (e) {
  124. if (e.code === 'EAGAIN') { // 'resource temporarily unavailable'
  125. // Happens on OS X 10.8.3 (not Windows 7!), if there no stdin input - typically when invoking a script without any input (for interactive stdin input)
  126. // If you were to just continue, you'd create a tight loop
  127. throw 'ERROR: interactive stdin input not supported.';
  128. } else if (e.code === 'EOF') {
  129. // Happens on Windows 7, but not OS X 10.8.3: simply signals the end of *piped* stdin input
  130. break;
  131. };
  132. throw e; // unexpected exception
  133. }
  134. if (!howManyRead || howManyRead === 0) { // No more stdin input available
  135. // OS X 10.8.3: regardless of input method, this is how the end of input is signaled
  136. // Windows 7: this is how the end of input is signaled for *interactive* stdin input
  137. break;
  138. }
  139. oldLength = bb.length;
  140. total += howManyRead;
  141. bb.write(buffer, 0, howManyRead);
  142. mayBeTotal += bb.length - oldLength;
  143. }
  144. return bb;
  145. }
  146. }
  147.  
  148. class LineReaderPromise {
  149. constructor(buffer) {
  150. this.buffer = buffer;
  151. this.index = 0;
  152. }
  153.  
  154. readLine() {
  155. let lineCode = "\n".charCodeAt(0), buffer = this.buffer;
  156. if (this.index === buffer.length) return null;
  157. if (buffer.byteAt(this.index) === "\n") {
  158. this.index++;
  159. return "";
  160. }
  161. let end = this.index, result;
  162. while (end < buffer.length) {
  163. if (lineCode === buffer.byteAt(end)) {
  164. result = buffer.slice(this.index, end).toString();
  165. this.index = end + 1;
  166. return result;
  167. }
  168. end = end + 1;
  169. }
  170. this.index = buffer.length;
  171. return buffer.slice(this.index, end).toString();
  172. }
  173.  
  174. eachLine(callback) {
  175. return new Promise((resolve, reject) => {
  176. let result;
  177. try {
  178. while (true) {
  179. var line = this.readLine();
  180. if (line === null) return resolve(this);
  181. callback(line);
  182. }
  183. } catch (e) {
  184. reject(e);
  185. }
  186. });
  187. }
  188.  
  189. static open(path) {
  190. return StreamBuffer
  191. .fromFile(path)
  192. .then(buffer => new LineReaderPromise(buffer))
  193. }
  194. }
  195.  
  196. module.exports = LineReaderPromise;
Add Comment
Please, Sign In to add comment