//****************************************************************************
// Filename: Csv.h
// Copyright 1999 Daniel X. Pape. All rights reserved.
//
// Description: A parser for a string of comma separated values.
//
// This is based on a similar class described in "The Practice of
// Programming" by Brian W. Kernighan and Rob Pike.
//
// Sample input: "foo",1,1.485,"la la lala","poit"
//
//****************************************************************************
// Revision History:
// Sunday, July 11, 1999 - Original
//****************************************************************************
#include "Csv.h"
using std::string;
// ***************************************************************************
// Function: Constructor
// Desc:
// ***************************************************************************
Csv::Csv(string line, string sep)
: nField_(0), line_(line), fieldSep_(sep)
{
split();
}
// ***************************************************************************
// Function: split
// Desc: Split line into fields
// ***************************************************************************
int Csv::split(void)
{
string field;
size_type i, j;
nField_ = 0;
if(line_.length() == 0)
return 0;
i = 0;
do {
if(i < line_.length() && line_[i] == '"')
j = advQuoted(line_, field, ++i); // skip quote
else
j = advPlain(line_, field, i);
if(nField_ >= fields_.size())
fields_.push_back(field);
else
fields_[nField_] = field;
nField_++;
i = j+1;
} while(j < line_.length());
return nField_;
}
// ***************************************************************************
// Function: advQuoted
// Desc: quoted field, return index of next separator
// ***************************************************************************
int Csv::advQuoted(const string& s, string& field, size_type i)
{
size_type j;
field = "";
for(j=i; j<s.length(); j++)
{
if(s[j] == '"' && s[++j] != '"')
{
size_type k = s.find_first_of(fieldSep_, j);
if(k > s.length()) // no sep found
k = s.length();
for(k -= j; k-- > 0; )
field += s[j++];
break;
}
field += s[j];
}
return j;
}
// ***************************************************************************
// Function: advPlain
// Desc: unquoted field, return index of next separator
// ***************************************************************************
int Csv::advPlain(const string& s, string& field, size_type i)
{
size_type j = s.find_first_of(fieldSep_, i);
if(j > s.length()) // no sep found
j = s.length();
field = string(s, i, j-i);
return j;
}
// ***************************************************************************
// Function: GetField
// Desc: return n-th field
// ***************************************************************************
string Csv::GetField(size_type n)
{
if(n > nField_)
return "";
else
return fields_[n];
}