Skip to content

Commit 514081d

Browse files
committed
add a generic line reader
Signed-off-by: Utkarsh Srivastava <srivastavautkarsh8097@gmail.com>
1 parent 2e31d10 commit 514081d

File tree

1 file changed

+56
-24
lines changed

1 file changed

+56
-24
lines changed

src/util/file_reader.js

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,30 @@
44

55
const nb_native = require('./nb_native');
66

7-
class NewlineReaderFilePathEntry {
8-
constructor(fs_context, filepath) {
9-
this.fs_context = fs_context;
10-
this.path = filepath;
11-
}
12-
13-
async open(mode = 'rw*') {
14-
return nb_native().fs.open(this.fs_context, this.path, mode);
15-
}
16-
}
17-
18-
class NewlineReader {
19-
/**
20-
* Newline character code
21-
*/
22-
static NL_CODE = 10;
23-
7+
class LineReader {
248
/**
25-
* NewlineReader allows to read a file line by line.
9+
* LineReader allows to read a file line by line.
2610
* @param {nb.NativeFSContext} fs_context
2711
* @param {string} filepath
12+
* @param {number | string} delim
2813
* @param {{
2914
* lock?: 'EXCLUSIVE' | 'SHARED'
3015
* bufsize?: number;
3116
* skip_leftover_line?: boolean;
3217
* skip_overflow_lines?: boolean;
3318
* read_file_offset?: number;
19+
* encoding?: BufferEncoding;
3420
* }} [cfg]
3521
**/
36-
constructor(fs_context, filepath, cfg) {
22+
constructor(fs_context, filepath, delim, cfg) {
23+
if (!['number', 'string'].includes(typeof(delim))) {
24+
throw new Error('delim must be of type string or a number');
25+
}
26+
3727
this.path = filepath;
3828
this.lock = cfg?.lock;
29+
this.delim = delim;
30+
this.encoding = cfg?.encoding || 'utf8';
3931
this.skip_leftover_line = Boolean(cfg?.skip_leftover_line);
4032
this.skip_overflow_lines = Boolean(cfg?.skip_overflow_lines);
4133

@@ -69,20 +61,22 @@ class NewlineReader {
6961
async nextline() {
7062
if (!this.fh) await this.init();
7163

64+
const delim_length = typeof this.delim === 'string' ? Buffer.byteLength(this.delim, this.encoding) : 1;
65+
7266
// TODO - in case more data will be appended to the file - after each read the reader must set reader.eof = false if someone will keep on reading from a file while it is being written.
7367
while (!this.eof) {
7468
// extract next line if terminated in current buffer
7569
if (this.start < this.end) {
76-
const term_idx = this.buf.subarray(this.start, this.end).indexOf(NewlineReader.NL_CODE);
70+
const term_idx = this.buf.subarray(this.start, this.end).indexOf(this.delim, null, this.encoding);
7771
if (term_idx >= 0) {
7872
if (this.overflow_state) {
7973
console.warn('line too long finally terminated:', this.info());
8074
this.overflow_state = false;
81-
this.start += term_idx + 1;
75+
this.start += term_idx + delim_length;
8276
continue;
8377
}
84-
const line = this.buf.toString('utf8', this.start, this.start + term_idx);
85-
this.start += term_idx + 1;
78+
const line = this.buf.toString(this.encoding, this.start, this.start + term_idx);
79+
this.start += term_idx + delim_length;
8680
this.next_line_file_offset = this.read_file_offset - (this.end - this.start);
8781
return line;
8882
}
@@ -120,7 +114,7 @@ class NewlineReader {
120114
} else if (this.overflow_state) {
121115
console.warn('line too long finally terminated at eof:', this.info());
122116
} else {
123-
const line = this.buf.toString('utf8', this.start, this.end);
117+
const line = this.buf.toString(this.encoding, this.start, this.end);
124118
this.start = this.end;
125119
this.next_line_file_offset = this.read_file_offset;
126120
return line;
@@ -204,5 +198,43 @@ class NewlineReader {
204198
}
205199
}
206200

201+
class NewlineReaderFilePathEntry {
202+
constructor(fs_context, filepath) {
203+
this.fs_context = fs_context;
204+
this.path = filepath;
205+
}
206+
207+
async open(mode = 'rw*') {
208+
return nb_native().fs.open(this.fs_context, this.path, mode);
209+
}
210+
}
211+
212+
class NewlineReader extends LineReader {
213+
/**
214+
* Newline character code
215+
*/
216+
static NL_CODE = 10;
217+
218+
/**
219+
* NewlineReader allows to read a file line by line.
220+
* @param {nb.NativeFSContext} fs_context
221+
* @param {string} filepath
222+
* @param {{
223+
* lock?: 'EXCLUSIVE' | 'SHARED'
224+
* bufsize?: number;
225+
* skip_leftover_line?: boolean;
226+
* skip_overflow_lines?: boolean;
227+
* read_file_offset?: number;
228+
* encoding?: BufferEncoding;
229+
* }} [cfg]
230+
**/
231+
constructor(fs_context, filepath, cfg) {
232+
super(fs_context, filepath, NewlineReader.NL_CODE, cfg)
233+
}
234+
235+
}
236+
207237
exports.NewlineReader = NewlineReader;
208238
exports.NewlineReaderEntry = NewlineReaderFilePathEntry;
239+
exports.LineReader = LineReader;
240+

0 commit comments

Comments
 (0)