Пример #1
0
bool CCSVParser::ParseRow (TArray<CString> &Row, CString *retsError)

//	ParseRow
//
//	Parses a row

	{
	enum EStates
		{
		stateStart,
		stateSingleQuote,
		stateDoubleQuote,
		stateInPlainValue,
		stateEndOfValue,
		stateCR,
		stateLF,
		};

	Row.DeleteAll();

	//	Parse the BOM, if any

	if (m_iFormat == formatUnknown)
		m_iFormat = ParseBOM();

	//	Keep reading until we hit the end of the line.

	EStates iState = stateStart;
	CBuffer Value;
	while (true)
		{
		switch (iState)
			{
			case stateStart:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case ' ':
					case '\t':
						break;

					case ',':
						Row.Insert(NULL_STR);
						break;

					case '\r':
						iState = stateCR;
						break;

					case '\n':
						iState = stateLF;
						break;

					case '\'':
						iState = stateSingleQuote;
						break;

					case '\"':
						iState = stateDoubleQuote;
						break;

					default:
						Value.WriteChar(GetCurChar());
						iState = stateInPlainValue;
						break;
					}
				break;
				}

			case stateSingleQuote:
				{
				switch (GetCurChar())
					{
					case '\0':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						return true;

					case '\'':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateEndOfValue;
						break;

					default:
						Value.WriteChar(GetCurChar());
						break;
					}
				break;
				}

			case stateDoubleQuote:
				{
				switch (GetCurChar())
					{
					case '\0':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						return true;

					case '\"':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateEndOfValue;
						break;

					default:
						Value.WriteChar(GetCurChar());
						break;
					}
				break;
				}

			case stateEndOfValue:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case ' ':
					case '\t':
						break;

					case ',':
						iState = stateStart;
						break;

					case '\r':
						iState = stateCR;
						break;

					case '\n':
						iState = stateLF;
						break;

					default:
						break;
					}
				break;
				}

			case stateInPlainValue:
				{
				switch (GetCurChar())
					{
					case '\0':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						return true;

					case ',':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateStart;
						break;

					case '\r':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateCR;
						break;

					case '\n':
						Row.Insert(CString(Value.GetPointer(), Value.GetLength()));
						Value.SetLength(0);
						iState = stateLF;
						break;

					default:
						Value.WriteChar(GetCurChar());
						break;
					}
				break;
				}

			case stateCR:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case '\n':
						GetNextChar();
						return true;

					default:
						break;
					}
				break;
				}

			case stateLF:
				{
				switch (GetCurChar())
					{
					case '\0':
						return true;

					case '\r':
						GetNextChar();
						return true;

					default:
						return true;
					}
				break;
				}
			}

		GetNextChar();
		}
	}