-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathindex.js
171 lines (142 loc) · 3.54 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* jshint node: true */
'use strict';
var fs = require('fs');
var Decoder = require('pull-utf8-decoder')
/**
# pull-file
This is a simple module which uses raw file reading methods available in
the node `fs` module to read files on-demand. It's a work in progress
and feedback is welcome :)
## Example Usage
<<< examples/ipsum-chunks.js
**/
module.exports = function(filename, opts) {
var mode = opts && opts.mode || 0x1B6; // 0666
var bufferSize = opts && opts.bufferSize || 1024*64;
var start = opts && opts.start || 0
var end = opts && opts.end || Number.MAX_SAFE_INTEGER
var fd = opts && opts.fd
var ended, closeNext, busy;
var _buffer = new Buffer(bufferSize)
var live = opts && !!opts.live
var liveCb, closeCb
var watcher
if(live) {
watcher = fs.watch(filename, {
persistent: opts.persistent !== false,
},
function (event) {
if(liveCb && event === 'change') {
var cb = liveCb
liveCb = null
closeNext = false
readNext(cb)
}
})
}
var flags = opts && opts.flags || 'r'
function readNext(cb) {
if(closeNext) {
if(!live) close(cb);
else liveCb = cb;
return
}
var toRead = Math.min(end - start, bufferSize);
busy = true;
fs.read(
fd,
_buffer,
0,
toRead,
start,
function(err, count, buffer) {
busy = false;
start += count;
// if we have received an end noticiation, just discard this data
if(closeNext && !live) {
close(closeCb);
return cb(closeNext);
}
if (ended) {
return cb(err || ended);
}
// if we encountered a read error pass it on
if (err) {
return cb(err);
}
if(count === buffer.length) {
cb(null, buffer);
} else if(count === 0 && live) {
liveCb = cb; closeNext = true
} else {
closeNext = true;
cb(null, buffer.slice(0, count));
}
}
);
_buffer = new Buffer(Math.min(end - start, bufferSize))
}
function open(cb) {
busy = true;
fs.open(filename, flags, mode, function(err, descriptor) {
// save the file descriptor
fd = descriptor;
busy = false
if(closeNext) {
close(closeCb);
return cb(closeNext);
}
if (err) {
return cb(err);
}
// read the next bytes
return readNext(cb);
});
}
function close (cb) {
if(!cb) throw new Error('close must have cb')
if(watcher) watcher.close()
//if auto close is disabled, then user manages fd.
if(opts && opts.autoClose === false) return cb(true)
//wait until we have got out of bed, then go back to bed.
//or if we are reading, wait till we read, then go back to bed.
else if(busy) {
closeCb = cb
return closeNext = true
}
//first read was close, don't even get out of bed.
else if(!fd) {
return cb(true)
}
//go back to bed
else {
fs.close(fd, function(err) {
fd = null;
cb(err || true);
});
}
}
function source (end, cb) {
if (end) {
ended = end;
live = false;
if(liveCb) {
liveCb(end || true);
}
close(cb);
}
// if we have already received the end notification, abort further
else if (ended) {
cb(ended);
}
else if (! fd) {
open(cb);
}
else
readNext(cb);
};
//read directly to text
if(opts && opts.encoding)
return Decoder(opts.encoding)(source)
return source
};