Exemplo n.º 1
0
        private void replaceConfig(Config config)
        {
            // Deep-copy the config so we can edit it
            Config configCopy = Papa.copy(config);

            //configCopy.chunkSize = parseInt(configCopy.chunkSize);	// parseInt VERY important so we don't concatenate strings!
            if (config.step == null && config.chunk == null)
            {
                configCopy.chunkSize = 0;  // disable Range header if not streaming; bad values break IIS - see issue #196
            }
            this._handle          = new ParserHandle(configCopy);
            this._handle.streamer = this;
            this._config          = configCopy; // persist the copy to the caller
        }
Exemplo n.º 2
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
                           }
                       }
            };
        }