Exemple #1
0
        /// <summary>
        /// Gets the string value for the specified range.
        /// </summary>
        /// <param name="range">Cell range.</param>
        /// <returns>String value for range.</returns>
        private object GetRawValueForRange(CsvCellRange range)
        {
            if (range.IsRowNumberVirtualCell)
            {
                return(this.RowNumber);
            }
            else if (range.Length == 0)
            {
                return(String.Empty);
            }

            // TODO: Hotspot
            string cell = _line.Substring(range.Start, range.Length);

            if (range.ContainsQuotes)
            {
                return(cell.Replace("\"\"", "\""));
            }

            return(cell);
        }
        private unsafe static CsvCellRange[] DelimeterRangeSplit(string item, char delim, bool includeRowNumber, out bool uneven, int maximum = 0)
        {
            uneven = false;
            // Size to construct an unknown range array.
            const int initialUnknownSize = 4;

            CsvCellRange[] row           = new CsvCellRange[maximum == 0 ? initialUnknownSize : maximum];
            int            currentColumn = 0;

            if (includeRowNumber)
            {
                row[0].IsRowNumberVirtualCell = true;
                currentColumn++;
            }

            const char   quote     = '\"';
            int          quotes    = 0;
            int          current   = 0;
            int          length    = item.Length;
            int          trimSize  = 0;
            bool         endOfLine = false;
            CsvCellRange final;

            // Pointer enumeration for the string helps shave around 20% of the cost over foreach char in string.
            // NOTE: A potential provement would be to do sizeof(intptr) enumeration, and mask
            fixed(char *pBuff = item)
            {
                for (int i = 0; i <= length; i++)
                {
                    if (pBuff[i] == quote)
                    {
                        ++quotes;
                    }

                    current++;

                    endOfLine = pBuff[i] == '\0';

                    // Are we at the end of a cell?
                    //  - End of line
                    //  - At a delimeter and not in a quote or next to a double quote
                    if (endOfLine ||
                        (pBuff[i] == delim && (quotes == 0 || ((pBuff[i - 1] == quote) && (quotes & 1) == 0))))
                    {
                        // Calculate how much to trim, if the cell is quoted, .e.g. "Value" this will strip the quotes at the start and end.
                        trimSize = quotes >= 2 ? 1 : 0;

                        //It's a stuct, this is fine.
                        final.Start                  = i - (current - 1) + trimSize;
                        final.Length                 = (current - 1) - (trimSize * 2);
                        final.ContainsQuotes         = quotes > 2;
                        final.IsRowNumberVirtualCell = false;

                        // Dont add empty last items if we dont know the size, we're done, get outa here
                        if (maximum == 0 && endOfLine && final.Length == 0)
                        {
                            break;
                        }

                        row[currentColumn] = final;
                        currentColumn++;

                        // Is there enough room left?
                        if (currentColumn == row.Length)
                        {
                            // If a maximum was specified, then exit, assume we've read enough
                            if (maximum > 0)
                            {
                                break;
                            }

                            // Otherwise grow the array.
                            Array.Resize(ref row, row.Length * 2);
                        }

                        // Safe to keep itereating, reset our tracking variables if we are not at the end of the string.

                        if (!endOfLine)
                        {
                            current = 0;
                            quotes  = 0;
                        }
                    }
                }
            }

            uneven = (quotes & 1) != 0;

            // If the size is not known, resize the array to the current column count
            if (maximum == 0)
            {
                Array.Resize(ref row, currentColumn);
            }

            return(row);
        }