#ifndef __CSV_H__
#define __CSV_H__
#define CSV_INVALID_INDEX ((size_t)(-1))
#define CSV_ZERO ((size_t)(0))
#define CSV_MAX_COLUMNS 0x20
#define CSV_HASH_TABLE_SIZE 0x80
typedef char * (*CASC_CSV_NEXTPROC)(void * pvUserData, char * szLine);
class CASC_CSV;
struct CASC_CSV_COLUMN
{
CASC_CSV_COLUMN()
{
szValue = NULL;
nLength = 0;
}
bool Empty() const
{
return (szValue == NULL || nLength == 0);
}
const char * szValue;
size_t nLength;
};
class CASC_CSV_LINE
{
public:
CASC_CSV_LINE();
~CASC_CSV_LINE();
bool SetLine(CASC_CSV * pParent, char * szLine);
const CASC_CSV_COLUMN & operator[](const char * szColumnName) const;
const CASC_CSV_COLUMN & operator[](size_t nIndex) const;
size_t GetColumnCount() const
{
return m_nColumns;
}
protected:
friend class CASC_CSV;
CASC_CSV * m_pParent;
CASC_CSV_COLUMN Columns[CSV_MAX_COLUMNS];
size_t m_nColumns;
};
class CASC_CSV
{
public:
CASC_CSV(size_t nLinesMax, bool bHasHeader);
~CASC_CSV();
DWORD SetNextLineProc(CASC_CSV_NEXTPROC PfnNextLineProc, CASC_CSV_NEXTPROC PfnNextColProc = NULL, void * pvUserData = NULL);
CASC_CSV_NEXTPROC GetNextColumnProc()
{
return PfnNextColumn;
}
DWORD Load(LPBYTE pbData, size_t cbData);
DWORD Load(LPCTSTR szFileName);
bool LoadNextLine();
const CASC_CSV_COLUMN & operator[](const char * szColumnName) const;
const CASC_CSV_LINE & operator[](size_t nIndex) const;
size_t GetHeaderColumns() const;
size_t GetColumnIndex(const char * szColumnName) const;
void * GetUserData() const
{
return m_pvUserData;
}
size_t GetLineCount() const
{
return m_nLines;
}
protected:
bool InitializeHashTable();
bool LoadNextLine(CASC_CSV_LINE & Line);
bool ParseCsvData();
CASC_CSV_NEXTPROC PfnNextLine;
CASC_CSV_NEXTPROC PfnNextColumn;
CASC_CSV_LINE * m_pLines;
CASC_CSV_LINE Header;
CASC_BLOB CsvFile;
BYTE HashTable[CSV_HASH_TABLE_SIZE];
void * m_pvUserData;
char * m_szCsvFile;
char * m_szCsvPtr;
size_t m_nLinesMax;
size_t m_nLines;
bool m_bHasHeader;
bool m_bHasAllLines;
};
#endif