internal bool ReadRow()
{
// currentChar is the first char after newlines
int currentChar = SkipAllNewLine();
if (currentChar < 0)
{
// nothing else to read
return false;
}
ReadState currentState = ReadState.TokenStart;
_columns = new ArrayList();
StringBuilder buffer = new StringBuilder();
while (currentState != ReadState.LineEnd)
{
switch(currentState)
{
// start of a token
case ReadState.TokenStart:
{
if (currentChar == _delimiter)
{
// it is the end of the token when we see a delimeter
// Store token, and reset state. and ignore this char
StoreTokenAndResetState(ref buffer, ref currentState);
}
else if (currentChar == '\"')
{
// jump to Quoted content if it token starts with a quote.
// and also ignore this quote
currentState = ReadState.QuotedContent;
}
else if (currentChar == '\n' ||
(currentChar == '\r' && _reader.Peek() == '\n'))
{
// we see a '\n' or '\r\n' sequence. Go to LineEnd
// ignore these chars
currentState = ReadState.LineEnd;
}
else
{
// safe to say that this is part of a unquoted content
buffer.Append((Char) currentChar);
currentState = ReadState.UnQuotedContent;
}
break;
}
// inside of an unquoted content
case ReadState.UnQuotedContent :
{
if (currentChar == _delimiter)
{
// It is then end of a toekn.
// Store the token value and reset state
// igore this char as well
StoreTokenAndResetState(ref buffer, ref currentState);
}
else if (currentChar == '\n' ||
(currentChar == '\r' && _reader.Peek() == '\n'))
{
// see a new line
// igorne these chars and jump to LineEnd
currentState = ReadState.LineEnd;
}
else
{
// we are good. store this char
// notice, even we see a '\"', we will just treat it like
// a normal char
buffer.Append((Char) currentChar);
}
break;
}
// inside of a quoted content
case ReadState.QuotedContent :
{
if (currentChar == '\"')
{
// now it depends on whether the next char is quote also
if (_reader.Peek() == '\"')
{
// we will ignore the next quote.
currentChar = _reader.Read();
buffer.Append( (Char) currentChar);
}
else
{ // we have a single quote. We fall back to unquoted content state
// and igorne the curernt quote
currentState = ReadState.UnQuotedContent;
}
}
else
{
// we are still inside of a quote, anything is accepted
buffer.Append((Char) currentChar);
}
break;
}
}
// read in the next char
currentChar = _reader.Read();
if (currentChar < 0)
{
// break out of the state machine if we reach the end of the file
break;
}
}
// we got to here either we are at LineEnd, or we are end of file
if (buffer.Length > 0)
{
_columns.Add(buffer.ToString());
}
return true;
}