/// <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); }