Files
m2dev-client-src/src/DumpProto/CsvFile.cpp
2026-01-05 15:58:48 +01:00

433 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "CsvFile.h"
#include <fstream>
#include <algorithm>
#ifndef Assert
#include <assert.h>
#define Assert assert
#define LogToFile (void)(0);
#endif
namespace
{
/// <20>Ľ̿<C4BD> state <20><><EFBFBD>Ű<EFBFBD>
enum ParseState
{
STATE_NORMAL = 0, ///< <20>Ϲ<EFBFBD> <20><><EFBFBD><EFBFBD>
STATE_QUOTE ///< <20><><EFBFBD><EFBFBD>ǥ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
};
/// <20><><EFBFBD>ڿ<EFBFBD> <20>¿<EFBFBD><C2BF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
std::string Trim(std::string str)
{
str = str.erase(str.find_last_not_of(" \t\r\n") + 1);
str = str.erase(0, str.find_first_not_of(" \t\r\n"));
return str;
}
/// \brief <20>־<EFBFBD><D6BE><EFBFBD> <20><><EFBFBD><20>ִ<EFBFBD> <20><><EFBFBD>ĺ<EFBFBD><C4BA><EFBFBD> <20><><EFBFBD> <20>ҹ<EFBFBD><D2B9>ڷ<EFBFBD> <20>ٲ۴<D9B2>.
std::string Lower(std::string original)
{
std::transform(original.begin(), original.end(), original.begin(), tolower);
return original;
}
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD> <20><>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
/// \param name <20><> <20≯<EFBFBD>
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
void cCsvAlias::AddAlias(const char* name, size_t index)
{
std::string converted(Lower(name));
Assert(m_Name2Index.find(converted) == m_Name2Index.end());
Assert(m_Index2Name.find(index) == m_Index2Name.end());
m_Name2Index.insert(NAME2INDEX_MAP::value_type(converted, index));
m_Index2Name.insert(INDEX2NAME_MAP::value_type(index, name));
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
void cCsvAlias::Destroy()
{
m_Name2Index.clear();
m_Index2Name.clear();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return const char* <20≯<EFBFBD>
////////////////////////////////////////////////////////////////////////////////
const char* cCsvAlias::operator [] (size_t index) const
{
INDEX2NAME_MAP::const_iterator itr(m_Index2Name.find(index));
if (itr == m_Index2Name.end())
{
LogToFile(NULL, "cannot find suitable conversion for %d", index);
Assert(false && "cannot find suitable conversion");
return NULL;
}
return itr->second.c_str();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param name <20≯<EFBFBD>
/// \return size_t <20><><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
size_t cCsvAlias::operator [] (const char* name) const
{
NAME2INDEX_MAP::const_iterator itr(m_Name2Index.find(Lower(name)));
if (itr == m_Name2Index.end())
{
LogToFile(NULL, "cannot find suitable conversion for %s", name);
Assert(false && "cannot find suitable conversion");
return 0;
}
return itr->second;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>Ѵ<EFBFBD>.
/// \param fileName CSV <20><><EFBFBD><EFBFBD> <20≯<EFBFBD>
/// \param seperator <20>ʵ<EFBFBD> <20>и<EFBFBD><D0B8>ڷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> '"'<27>̴<EFBFBD>.
/// \return bool <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ߴٸ<DFB4> true, <20>ƴ϶<C6B4><CFB6> false
////////////////////////////////////////////////////////////////////////////////
bool cCsvFile::Load(const char* fileName, const char seperator, const char quote)
{
Assert(seperator != quote);
// Open file in binary mode to preserve UTF-8 encoding
std::ifstream file(fileName, std::ios::in | std::ios::binary);
if (!file) return false;
Destroy(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD>
cCsvRow* row = NULL;
ParseState state = STATE_NORMAL;
std::string token = "";
char buf[2048+1] = {0,};
while (file.good())
{
file.getline(buf, 2048);
buf[sizeof(buf)-1] = 0;
std::string line(Trim(buf));
if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue;
std::string text = std::string(line) + " "; // <20>Ľ<EFBFBD> lookahead <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF>ش<EFBFBD>.
size_t cur = 0;
while (cur < text.size())
{
// <20><><EFBFBD><EFBFBD> <20><>尡 QUOTE <20><><EFBFBD><EFBFBD><EFBFBD> <20><>,
if (state == STATE_QUOTE)
{
// '"' <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>.
// 1. <20><> <20><><EFBFBD>ο<EFBFBD> Ư<><C6AF> <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20≯<EFBFBD> <20>˸<EFBFBD><CBB8><EFBFBD> <20><> <20>¿<EFBFBD><C2BF><EFBFBD> <20><>
// 2. <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> '"' 2<><32><EFBFBD><EFBFBD> ġȯ<C4A1><C8AF> <20><>
// <20><> <20><> ù<><C3B9>° <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̶<EFBFBD><CCB6>,
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> STATE_NORMAL<41><4C> <20>ɸ<EFBFBD><C9B8><EFBFBD> <20>Ǿ<EFBFBD><C7BE>ִ<EFBFBD>.
// <20>׷<EFBFBD><D7B7>Ƿ<EFBFBD> <20><><EFBFBD><20>ɸ<EFBFBD><C9B8><EFBFBD> <20><><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>쳪, 2<><32> <20><><EFBFBD> <20><><EFBFBD>̴<EFBFBD>.
// 2<><32><EFBFBD><EFBFBD> <20><><EFBFBD><ECBFA1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> 2<><32><EFBFBD><EFBFBD> <20><>Ÿ<EFBFBD><C5B8><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 1<><31><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><ECBFA1> <20>ƴϴ<C6B4>. <20≯<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ؼ<EFBFBD> <20>ڵ带 ¥<><C2A5>...
if (text[cur] == quote)
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> '"' <20><><EFBFBD>ڶ<EFBFBD><DAB6>, <20><> <20><><EFBFBD>ӵ<EFBFBD> '"' <20><><EFBFBD>ڶ<EFBFBD><DAB6>
// <20>̴<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> ġȯ<C4A1><C8AF> <20><><EFBFBD>̴<EFBFBD>.
if (text[cur+1] == quote)
{
token += quote;
++cur;
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڰ<EFBFBD> '"' <20><><EFBFBD>ڰ<EFBFBD> <20>ƴ϶<C6B4><CFB6>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"'<27><><EFBFBD>ڴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>˸<EFBFBD><CBB8><EFBFBD> <20><><EFBFBD>ڶ<EFBFBD><DAB6> <20><> <20><> <20>ִ<EFBFBD>.
else
{
state = STATE_NORMAL;
}
}
else
{
token += text[cur];
}
}
// <20><><EFBFBD><EFBFBD> <20><>尡 NORMAL <20><><EFBFBD><EFBFBD><EFBFBD> <20><>,
else if (state == STATE_NORMAL)
{
if (row == NULL)
row = new cCsvRow();
// ',' <20><><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ǹ<EFBFBD><C7B9>Ѵ<EFBFBD>.
// <20><>ū<EFBFBD><C5AB><EFBFBD>μ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE><EFBFBD>ٰ<EFBFBD> <20><><EFBFBD><EFBFBD>ְ<EFBFBD>, <20><>ū<EFBFBD><C5AB> <20>ʱ<EFBFBD>ȭ<EFBFBD>Ѵ<EFBFBD>.
if (text[cur] == seperator)
{
row->push_back(token);
token.clear();
}
// '"' <20><><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ٸ<EFBFBD>, QUOTE <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
else if (text[cur] == quote)
{
state = STATE_QUOTE;
}
// <20>ٸ<EFBFBD> <20>Ϲ<EFBFBD> <20><><EFBFBD>ڶ<EFBFBD><DAB6> <20><><EFBFBD><EFBFBD> <20><>ū<EFBFBD><C5AB><EFBFBD>ٰ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>.
else
{
token += text[cur];
}
}
++cur;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ',' <20><><EFBFBD>ڰ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><20>߰<EFBFBD><DFB0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
// <20><>, ó<><C3B3><EFBFBD><EFBFBD> <20>Ľ<EFBFBD> lookahead <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if (state == STATE_NORMAL)
{
Assert(row != NULL);
row->push_back(token.substr(0, token.size()-2));
m_Rows.push_back(row);
token.clear();
row = NULL;
}
else
{
token = token.substr(0, token.size()-2) + "\r\n";
}
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CSV <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
/// \param fileName CSV <20><><EFBFBD><EFBFBD> <20≯<EFBFBD>
/// \param append true<75><65> <20><><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>. false<73><65> <20><><EFBFBD><ECBFA1>
/// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϰ<EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
/// \param seperator <20>ʵ<EFBFBD> <20>и<EFBFBD><D0B8>ڷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> '"'<27>̴<EFBFBD>.
/// \return bool <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ߴٸ<DFB4> true, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><ECBFA1> false
////////////////////////////////////////////////////////////////////////////////
bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const
{
Assert(seperator != quote);
// <20><><EFBFBD> <20><><20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>÷<EFBFBD><C3B7>׷<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
std::ofstream file;
if (append) { file.open(fileName, std::ios::out | std::ios::app); }
else { file.open(fileName, std::ios::out | std::ios::trunc); }
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ߴٸ<DFB4>, false<73><65> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if (!file) return false;
char special_chars[5] = { seperator, quote, '\r', '\n', 0 };
char quote_escape_string[3] = { quote, quote, 0 };
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD> Ⱦ<><C8BE><EFBFBD>ϸ鼭...
for (size_t i=0; i<m_Rows.size(); i++)
{
const cCsvRow& row = *((*this)[i]);
std::string line;
// <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><>ū<EFBFBD><C5AB> Ⱦ<><C8BE><EFBFBD>ϸ鼭...
for (size_t j=0; j<row.size(); j++)
{
const std::string& token = row[j];
// <20>Ϲ<EFBFBD><CFB9><EFBFBD><EFBFBD><EFBFBD>('"' <20>Ǵ<EFBFBD> ','<27><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
// <20><>ū<EFBFBD>̶<EFBFBD><CCB6> <20>׳<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> <20>ȴ<EFBFBD>.
if (token.find_first_of(special_chars) == std::string::npos)
{
line += token;
}
// Ư<><C6AF><EFBFBD><EFBFBD><EFBFBD>ڸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ū<EFBFBD>̶<EFBFBD><CCB6> <20><><EFBFBD>ڿ<EFBFBD> <20>¿쿡 '"'<27><> <20>ٿ<EFBFBD><D9BF>ְ<EFBFBD>,
// <20><><EFBFBD>ڿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"'<27><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
else
{
line += quote;
for (size_t k=0; k<token.size(); k++)
{
if (token[k] == quote) line += quote_escape_string;
else line += token[k];
}
line += quote;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ƴ϶<C6B4><CFB6> ','<27><> <20><>ū<EFBFBD><C5AB> <20>ڿ<EFBFBD><DABF><EFBFBD> <20>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
if (j != row.size() - 1) { line += seperator; }
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
file << line << std::endl;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20>޸𸮿<DEB8><F0B8AEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
void cCsvFile::Destroy()
{
for (ROWS::iterator itr(m_Rows.begin()); itr != m_Rows.end(); ++itr)
delete *itr;
m_Rows.clear();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return cCsvRow* <20>ش<EFBFBD> <20><>
////////////////////////////////////////////////////////////////////////////////
cCsvRow* cCsvFile::operator [] (size_t index)
{
Assert(index < m_Rows.size());
return m_Rows[index];
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ش<EFBFBD><D8B4>ϴ<EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return const cCsvRow* <20>ش<EFBFBD> <20><>
////////////////////////////////////////////////////////////////////////////////
const cCsvRow* cCsvFile::operator [] (size_t index) const
{
Assert(index < m_Rows.size());
return m_Rows[index];
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
cCsvTable::cCsvTable()
: m_CurRow(-1)
{
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>Ҹ<EFBFBD><D2B8><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
cCsvTable::~cCsvTable()
{
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> CSV <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>Ѵ<EFBFBD>.
/// \param fileName CSV <20><><EFBFBD><EFBFBD> <20≯<EFBFBD>
/// \param seperator <20>ʵ<EFBFBD> <20>и<EFBFBD><D0B8>ڷ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><EFBFBD><E2BABB><EFBFBD><EFBFBD> '"'<27>̴<EFBFBD>.
/// \return bool <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5>ߴٸ<DFB4> true, <20>ƴ϶<C6B4><CFB6> false
////////////////////////////////////////////////////////////////////////////////
bool cCsvTable::Load(const char* fileName, const char seperator, const char quote)
{
Destroy();
return m_File.Load(fileName, seperator, quote);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѿ<D1BE><EEB0A3>.
/// \return bool <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѿ <20><><EFBFBD> true<75><65> <20><>ȯ<EFBFBD>ϰ<EFBFBD>, <20><> <20>̻<EFBFBD>
/// <20>Ѿ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ<EFBFBD> <20><><EFBFBD><ECBFA1> false<73><65> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
bool cCsvTable::Next()
{
// 20<32><30><EFBFBD> <20><><EFBFBD><EFBFBD> ȣ<><C8A3><EFBFBD>ϸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>÷ΰ<C3B7> <20>Ͼ<CFBE>ٵ<EFBFBD>...<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?
return ++m_CurRow < (int)m_File.GetRowCount() ? true : false;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>ڸ<EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \return size_t <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
////////////////////////////////////////////////////////////////////////////////
size_t cCsvTable::ColCount() const
{
return CurRow()->size();
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> int <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return int <20><> <20><>
////////////////////////////////////////////////////////////////////////////////
int cCsvTable::AsInt(size_t index) const
{
const cCsvRow* const row = CurRow();
Assert(row);
Assert(index < row->size());
return row->AsInt(index);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> double <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return double <20><> <20><>
////////////////////////////////////////////////////////////////////////////////
double cCsvTable::AsDouble(size_t index) const
{
const cCsvRow* const row = CurRow();
Assert(row);
Assert(index < row->size());
return row->AsDouble(index);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20>̿<EFBFBD><CCBF><EFBFBD> std::string <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \param index <20><> <20>ε<EFBFBD><CEB5><EFBFBD>
/// \return const char* <20><> <20><>
////////////////////////////////////////////////////////////////////////////////
const char* cCsvTable::AsStringByIndex(size_t index) const
{
const cCsvRow* const row = CurRow();
Assert(row);
Assert(index < row->size());
return row->AsString(index);
}
////////////////////////////////////////////////////////////////////////////////
/// \brief alias<61><73> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
void cCsvTable::Destroy()
{
m_File.Destroy();
m_Alias.Destroy();
m_CurRow = -1;
}
////////////////////////////////////////////////////////////////////////////////
/// \brief <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
/// \return const cCsvRow* <20>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><ECBFA1> <20><> <20><><EFBFBD><EFBFBD>
/// <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><>ȯ<EFBFBD>ϰ<EFBFBD>, <20><> <20>̻<EFBFBD> <20>׼<EFBFBD><D7BC><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><ECBFA1> NULL<4C><4C>
/// <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
////////////////////////////////////////////////////////////////////////////////
const cCsvRow* const cCsvTable::CurRow() const
{
if (m_CurRow < 0)
{
Assert(false && "call Next() first!");
return NULL;
}
else if (m_CurRow >= (int)m_File.GetRowCount())
{
Assert(false && "no more rows!");
return NULL;
}
return m_File[m_CurRow];
}