|
|
|
@ -394,11 +394,23 @@
@@ -394,11 +394,23 @@
|
|
|
|
|
var start = 0, fileSize = 0; |
|
|
|
|
var aggregate = ""; |
|
|
|
|
var partialLine = ""; |
|
|
|
|
var xhr, nextChunk; |
|
|
|
|
var xhr, url, nextChunk, finishedWithEntireFile; |
|
|
|
|
var handle = new ParserHandle(copy(config)); |
|
|
|
|
handle.streamer = this; |
|
|
|
|
|
|
|
|
|
this.stream = function(url) |
|
|
|
|
this.resume = function() |
|
|
|
|
{ |
|
|
|
|
nextChunk(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.finished = function() |
|
|
|
|
{ |
|
|
|
|
return finishedWithEntireFile; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.stream = function(u) |
|
|
|
|
{ |
|
|
|
|
url = u; |
|
|
|
|
if (IS_WORKER) |
|
|
|
|
{ |
|
|
|
|
nextChunk = function() |
|
|
|
@ -416,10 +428,16 @@
@@ -416,10 +428,16 @@
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
nextChunk(); // Starts streaming
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function readChunk() |
|
|
|
|
{ |
|
|
|
|
if (finishedWithEntireFile) |
|
|
|
|
{ |
|
|
|
|
chunkLoaded(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
xhr = new XMLHttpRequest(); |
|
|
|
|
if (!IS_WORKER) |
|
|
|
|
{ |
|
|
|
@ -456,7 +474,7 @@
@@ -456,7 +474,7 @@
|
|
|
|
|
aggregate += partialLine + xhr.responseText; |
|
|
|
|
partialLine = ""; |
|
|
|
|
|
|
|
|
|
var finishedWithEntireFile = !config.step || start > getFileSize(xhr); |
|
|
|
|
finishedWithEntireFile = !config.step || start > getFileSize(xhr); |
|
|
|
|
|
|
|
|
|
if (!finishedWithEntireFile) |
|
|
|
|
{ |
|
|
|
@ -492,6 +510,7 @@
@@ -492,6 +510,7 @@
|
|
|
|
|
} |
|
|
|
|
else if (isFunction(config.chunk)) |
|
|
|
|
{ |
|
|
|
|
console.log("CHUNKED"); |
|
|
|
|
config.chunk(results); |
|
|
|
|
results = undefined; |
|
|
|
|
} |
|
|
|
@ -519,7 +538,6 @@
@@ -519,7 +538,6 @@
|
|
|
|
|
var contentRange = xhr.getResponseHeader("Content-Range"); |
|
|
|
|
return parseInt(contentRange.substr(contentRange.lastIndexOf("/") + 1)); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -537,18 +555,22 @@
@@ -537,18 +555,22 @@
|
|
|
|
|
config.chunkSize = Papa.LocalChunkSize; |
|
|
|
|
|
|
|
|
|
var start = 0; |
|
|
|
|
var file; |
|
|
|
|
var slice; |
|
|
|
|
var aggregate = ""; |
|
|
|
|
var partialLine = ""; |
|
|
|
|
var reader, nextChunk, slice; |
|
|
|
|
var reader, nextChunk, slice, finishedWithEntireFile; |
|
|
|
|
var handle = new ParserHandle(copy(config)); |
|
|
|
|
handle.streamer = this; |
|
|
|
|
|
|
|
|
|
// FileReader is better than FileReaderSync (even in worker) - see http://stackoverflow.com/q/24708649/1048862
|
|
|
|
|
// But Firefox is a pill, too - see issue #76: https://github.com/mholt/PapaParse/issues/76
|
|
|
|
|
var usingAsyncReader = typeof FileReader === 'function'; |
|
|
|
|
|
|
|
|
|
this.stream = function(file) |
|
|
|
|
this.stream = function(f) |
|
|
|
|
{ |
|
|
|
|
var slice = file.slice || file.webkitSlice || file.mozSlice; |
|
|
|
|
file = f; |
|
|
|
|
slice = file.slice || file.webkitSlice || file.mozSlice; |
|
|
|
|
|
|
|
|
|
if (usingAsyncReader) |
|
|
|
|
{ |
|
|
|
@ -560,10 +582,21 @@
@@ -560,10 +582,21 @@
|
|
|
|
|
reader = new FileReaderSync(); // Hack for running in a web worker in Firefox
|
|
|
|
|
|
|
|
|
|
nextChunk(); // Starts streaming
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.finished = function() |
|
|
|
|
{ |
|
|
|
|
return finishedWithEntireFile; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.resume = function() |
|
|
|
|
{ |
|
|
|
|
nextChunk(); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function nextChunk() |
|
|
|
|
{ |
|
|
|
|
if (start < file.size) |
|
|
|
|
if (!finishedWithEntireFile) |
|
|
|
|
readChunk(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -584,7 +617,7 @@
@@ -584,7 +617,7 @@
|
|
|
|
|
aggregate += partialLine + event.target.result; |
|
|
|
|
partialLine = ""; |
|
|
|
|
|
|
|
|
|
var finishedWithEntireFile = start >= file.size; |
|
|
|
|
finishedWithEntireFile = start >= file.size; |
|
|
|
|
|
|
|
|
|
if (!finishedWithEntireFile) |
|
|
|
|
{ |
|
|
|
@ -624,7 +657,7 @@
@@ -624,7 +657,7 @@
|
|
|
|
|
results = undefined; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!finishedWithEntireFile && !results.meta.paused) |
|
|
|
|
if (!results || !results.meta.paused) |
|
|
|
|
nextChunk(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -642,7 +675,7 @@
@@ -642,7 +675,7 @@
|
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -656,6 +689,7 @@
@@ -656,6 +689,7 @@
|
|
|
|
|
var FLOAT = /^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i; |
|
|
|
|
|
|
|
|
|
var self = this; |
|
|
|
|
var _stepCounter = 0; // Number of times step was called (number of rows parsed)
|
|
|
|
|
var _input; // The input being parsed
|
|
|
|
|
var _parser; // The core parser being used
|
|
|
|
|
var _paused = false; // Whether we are paused or not
|
|
|
|
@ -666,10 +700,29 @@
@@ -666,10 +700,29 @@
|
|
|
|
|
errors: [], |
|
|
|
|
meta: {} |
|
|
|
|
}; |
|
|
|
|
_config = copy(_config); |
|
|
|
|
|
|
|
|
|
if (isFunction(_config.step)) |
|
|
|
|
{ |
|
|
|
|
var userStep = _config.step; |
|
|
|
|
_config.step = function(results) |
|
|
|
|
{ |
|
|
|
|
_results = results; |
|
|
|
|
if (needsHeaderRow()) |
|
|
|
|
processResults(); |
|
|
|
|
else // only call user's step function after header row
|
|
|
|
|
{ |
|
|
|
|
_stepCounter += results.data.length; |
|
|
|
|
if (_config.preview && _stepCounter > _config.preview) |
|
|
|
|
_parser.abort(); |
|
|
|
|
else |
|
|
|
|
userStep(processResults(), self); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
this.parse = function(input) |
|
|
|
|
{ |
|
|
|
|
//_stepCounter = 0;
|
|
|
|
|
_delimiterError = false; |
|
|
|
|
if (!_config.delimiter) |
|
|
|
|
{ |
|
|
|
@ -684,29 +737,17 @@
@@ -684,29 +737,17 @@
|
|
|
|
|
_results.meta.delimiter = _config.delimiter; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (isFunction(_config.step)) |
|
|
|
|
{ |
|
|
|
|
var userStep = _config.step; |
|
|
|
|
_config.step = function(results) |
|
|
|
|
{ |
|
|
|
|
_results = results; |
|
|
|
|
if (needsHeaderRow()) |
|
|
|
|
processResults(); |
|
|
|
|
else |
|
|
|
|
userStep(processResults(), self); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var parserConfig = copy(_config); |
|
|
|
|
if (_config.preview && _config.header) |
|
|
|
|
_config.preview++; // to compensate for header row
|
|
|
|
|
parserConfig.preview++; // to compensate for header row
|
|
|
|
|
|
|
|
|
|
_input = input; |
|
|
|
|
_parser = new Parser(_config); |
|
|
|
|
_parser = new Parser(parserConfig); |
|
|
|
|
_results = _parser.parse(_input); |
|
|
|
|
processResults(); |
|
|
|
|
if (isFunction(_config.complete) && !_paused) |
|
|
|
|
_config.complete(_results); |
|
|
|
|
return _paused ? { meta: { paused: true } } : _results; |
|
|
|
|
if (isFunction(_config.complete) && !_paused && (!self.streamer || self.streamer.finished())) |
|
|
|
|
_config.complete(_results); // TODO: In some cases, when chunk is specified, this executes before the chunk function...
|
|
|
|
|
return _paused ? { meta: { paused: true } } : (_results || { meta: { paused: false } }); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.pause = function() |
|
|
|
@ -721,8 +762,13 @@
@@ -721,8 +762,13 @@
|
|
|
|
|
_paused = false; |
|
|
|
|
_parser = new Parser(_config); |
|
|
|
|
_parser.parse(_input); |
|
|
|
|
if (isFunction(_config.complete) && !_paused) |
|
|
|
|
if (!_paused) |
|
|
|
|
{ |
|
|
|
|
if (self.streamer && !self.streamer.finished()) |
|
|
|
|
self.streamer.resume(); // more of the file yet to come
|
|
|
|
|
else if (isFunction(_config.complete)) |
|
|
|
|
_config.complete(_results); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
this.abort = function() |
|
|
|
@ -731,7 +777,7 @@
@@ -731,7 +777,7 @@
|
|
|
|
|
if (isFunction(_config.complete)) |
|
|
|
|
_config.complete(_results); |
|
|
|
|
_input = ""; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
function processResults() |
|
|
|
|
{ |
|
|
|
@ -743,7 +789,6 @@
@@ -743,7 +789,6 @@
|
|
|
|
|
|
|
|
|
|
if (needsHeaderRow()) |
|
|
|
|
fillHeaderFields(); |
|
|
|
|
|
|
|
|
|
return applyHeaderAndDynamicTyping(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -770,6 +815,7 @@
@@ -770,6 +815,7 @@
|
|
|
|
|
for (var i = 0; i < _results.data.length; i++) |
|
|
|
|
{ |
|
|
|
|
var row = {}; |
|
|
|
|
|
|
|
|
|
for (var j = 0; j < _results.data[i].length; j++) |
|
|
|
|
{ |
|
|
|
|
if (_config.dynamicTyping) |
|
|
|
@ -808,7 +854,6 @@
@@ -808,7 +854,6 @@
|
|
|
|
|
|
|
|
|
|
if (_config.header && _results.meta) |
|
|
|
|
_results.meta.fields = _fields; |
|
|
|
|
|
|
|
|
|
return _results; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|