Exemple #1
0
 public void abort()
 {
     _aborted = true;
     _parser.abort();
     _results.meta.aborted = true;
     if (Papa.isFunction(_config.complete))
     {
         _config.complete(_results);
     }
     _input = "";
 }
 protected void _sendError(Error error)
 {
     if (Papa.isFunction(this._config.error))
     {
         this._config.error(error);
     }
     else if (Papa.IS_WORKER && this._config.error != null)
     {
         //global.postMessage({
         //    workerId: Papa.WORKER_ID,
         //    error: error,
         //    finished: false
         //});
     }
 }
        public Result parseChunk(string chunk)
        {
            // First chunk pre-processing
            if (this.isFirstChunk && Papa.isFunction(this._config.beforeFirstChunk))
            {
                string modifiedChunk = this._config.beforeFirstChunk(chunk);
                if (modifiedChunk != null)
                {
                    chunk = modifiedChunk;
                }
            }
            this.isFirstChunk = false;

            // Rejoin the line we likely just split in two by chunking the file
            string aggregate = this._partialLine + chunk;

            this._partialLine = "";

            Result results = this._handle.parse(aggregate, this._baseIndex, !this._finished);

            if (this._handle.paused() || this._handle.aborted())
            {
                return(null);
            }

            int lastIndex = results.meta.cursor;

            if (!this._finished)
            {
                this._partialLine = Papa.Substring(aggregate, lastIndex - this._baseIndex);
                this._baseIndex   = lastIndex;
            }

            if (results != null && results.data != null)
            {
                this._rowCount += results.data.Count;
            }

            bool finishedIncludingPreview = this._finished || (this._config.preview > 0 && this._rowCount >= this._config.preview);

            if (Papa.IS_WORKER)
            {
                //global.postMessage({
                //    results: results,
                //    workerId: Papa.WORKER_ID,
                //    finished: finishedIncludingPreview
                //});
            }
            else if (Papa.isFunction(this._config.chunk))
            {
                this._config.chunk(results, this._handle);
                if (this._paused)
                {
                    return(null);
                }
                results = null;
                this._completeResults = null;
            }

            if (this._config.step == null && this._config.chunk == null)
            {
                this._completeResults.data = this._completeResults.data.Concat(results.data).ToList();

                this._completeResults.dataWithHeader = this._completeResults.dataWithHeader.Concat(results.dataWithHeader).ToList();
                this._completeResults.errors         = this._completeResults.errors.Concat(results.errors).ToList();
                this._completeResults.meta           = results.meta;
            }

            if (finishedIncludingPreview && Papa.isFunction(this._config.complete) && (results == null || !results.meta.aborted))
            {
                this._config.complete(this._completeResults);
            }

            if (!finishedIncludingPreview && (results == null || !results.meta.paused))
            {
                this._nextChunk();
            }

            return(results);
        }
Exemple #4
0
        // Parses input. Most users won't need, and shouldn't mess with, the baseIndex
        // and ignoreLastRow parameters. They are used by streamers (wrapper functions)
        // when an input comes in multiple chunks, like from a file.
        public Result parse(string input, int baseIndex = 0, bool ignoreLastRow = false)
        {
            Func <bool> needsHeaderRow = () =>
            {
                return(_config.header && _fields.Count == 0);
            };

            Action fillHeaderFields = () =>
            {
                if (_results == null || _results.data.Count == 0)
                {
                    return;
                }
                for (int i = 0; needsHeaderRow() && i < _results.data.Count; i++)
                {
                    for (int j = 0; j < _results.data[i].Count; j++)
                    {
                        _fields.Add(_results.data[i][j]);
                    }
                }
                _results.data.RemoveRange(0, 1);
            };

            Func <Result> applyHeaderAndDynamicTyping = () =>
            {
                if (_results == null || (!_config.header && !_config.dynamicTyping))
                {
                    return(_results);
                }

                for (int i = 0; i < _results.data.Count; i++)
                {
                    Dictionary <string, string> rowWithHeader = new Dictionary <string, string>();

                    int j;
                    for (j = 0; j < _results.data[i].Count; j++)
                    {
                        //[TODO]
                        //if (_config.dynamicTyping)
                        //{
                        //    var value = _results.data[i][j];
                        //    if (value == "true" || value == "TRUE")
                        //        _results.data[i][j] = true;
                        //    else if (value == "false" || value == "FALSE")
                        //        _results.data[i][j] = false;
                        //    else
                        //        _results.data[i][j] = tryParseFloat(value);
                        //}

                        if (_config.header)
                        {
                            if (j >= _fields.Count)
                            {
                                if (!rowWithHeader.ContainsKey("__parsed_extra"))
                                {
                                    rowWithHeader.Add("__parsed_extra", "");
                                }
                                rowWithHeader["__parsed_extra"] += _results.data[i][j];
                                //[CR we can not simply put an Array into __parsed_extra, so juste pipe it]
                                if (j < _results.data[i].Count - 1)
                                {
                                    rowWithHeader["__parsed_extra"] += "|";
                                }
                            }
                            else
                            {
                                rowWithHeader[_fields[j]] = _results.data[i][j];
                            }
                        }
                    }

                    if (_config.header)
                    {
                        _results.dataWithHeader.Add(rowWithHeader); //[CR we are not overwriting _results.data here but instead fill another List]
                        if (j > _fields.Count)
                        {
                            addError("FieldMismatch", "TooManyFields", "Too many fields: expected " + _fields.Count + " fields but parsed " + j, i);
                        }
                        else if (j < _fields.Count)
                        {
                            addError("FieldMismatch", "TooFewFields", "Too few fields: expected " + _fields.Count + " fields but parsed " + j, i);
                        }
                    }
                }

                if (_config.header && _results.meta != null)
                {
                    _results.meta.fields = _fields;
                }
                return(_results);
            };

            Func <Result> processResults = () =>
            {
                if (_results != null && _delimiterError)
                {
                    addError("Delimiter", "UndetectableDelimiter", "Unable to auto-detect delimiting character; defaulted to '" + Papa.DefaultDelimiter + "'");
                    _delimiterError = false;
                }

                if (_config.skipEmptyLines)
                {
                    for (int i = 0; i < _results.data.Count; i++)
                    {
                        if (_results.data[i].Count == 1 && _results.data[i][0] == "")
                        {
                            _results.data.RemoveRange(i--, 1);
                        }
                    }
                }

                if (needsHeaderRow())
                {
                    fillHeaderFields();
                }

                return(applyHeaderAndDynamicTyping());
            };

            //------------------------------------------------------------------------------------------------------------------------------------------------------

            if (String.IsNullOrEmpty(_config.newline))
            {
                _config.newline = guessLineEndings(input);
            }

            _delimiterError = false;
            if (String.IsNullOrEmpty(_config.delimiter))
            {
                DelimiterResult delimGuess = guessDelimiter(input);
                if (delimGuess.successful)
                {
                    _config.delimiter = delimGuess.bestDelimiter;
                }
                else
                {
                    _delimiterError   = true;                   // add error after parsing (otherwise it would be overwritten)
                    _config.delimiter = Papa.DefaultDelimiter;
                }
                _results.meta.delimiter = _config.delimiter;
            }

            if (_config.quoteChar == Char.MinValue)
            {
                if (Papa.Substr(input, 0, 1) == "'" && Papa.Substr(input, input.IndexOf(_config.delimiter, 0) - 1, 1) == "'")
                {
                    _config.quoteChar = '\'';
                }
                else
                {
                    _config.quoteChar = '"';
                }
            }

            Config parserConfig = Papa.copy(_config);

            if (_config.preview > 0 && _config.header)
            {
                parserConfig.preview++;                 // to compensate for header row
            }
            if (Papa.isFunction(_config.step))
            {
                Action <Result, ParserHandle> userStep = _config.step;
                parserConfig.step = (results, parser) =>
                {
                    _results = results;

                    if (needsHeaderRow())
                    {
                        processResults();
                    }
                    else        // only call user's step function after header row
                    {
                        processResults();

                        // It's possbile that this line was empty and there's no row here after all
                        if (_results.data.Count == 0)
                        {
                            return;
                        }

                        _stepCounter += results.data.Count;
                        if (parserConfig.preview > 0 && _stepCounter > parserConfig.preview)
                        {
                            _parser.abort();
                        }
                        else
                        {
                            userStep(_results, this);
                        }
                    }
                };
            }
            //----------------------------------------------------------------------

            _input   = input;
            _parser  = new Parser(parserConfig);
            _results = _parser.parse(_input, baseIndex, ignoreLastRow);
            processResults();

            if (_paused)
            {
                return new Result()
                       {
                           meta = new Meta()
                           {
                               paused = true
                           }
                       }
            }
            ;
            else if (_results != null)
            {
                return(_results);
            }
            else
            {
                return new Result()
                       {
                           meta = new Meta()
                           {
                               paused = false
                           }
                       }
            };
        }