forked from metin2/server
431 lines
14 KiB
C++
431 lines
14 KiB
C++
|
#include "stdafx.h"
|
|||
|
#include "CsvReader.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><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><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20≯<EFBFBD><CCB8><EFBFBD> <20><><EFBFBD><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><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><EFBFBD> <20><><EFBFBD><EFBFBD>. <20>⺻<EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
|
|||
|
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><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><EFBFBD> false
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
bool cCsvFile::Load(const char* fileName, const char seperator, const char quote)
|
|||
|
{
|
|||
|
Assert(seperator != quote);
|
|||
|
|
|||
|
std::ifstream file(fileName, std::ios::in);
|
|||
|
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><><EFBFBD>尡 QUOTE <20><><EFBFBD><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><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><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><EFBFBD>,
|
|||
|
// <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><><EFBFBD>쳪, 2<><32> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̴<EFBFBD>.
|
|||
|
// 2<><32><EFBFBD><EFBFBD> <20><><EFBFBD>쿡<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>쿡<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><EFBFBD>, <20><> <20><><EFBFBD>ӵ<EFBFBD> '"' <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD>
|
|||
|
// <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><EFBFBD>
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> '"'<27><><EFBFBD>ڴ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>˸<EFBFBD><CBB8><EFBFBD> <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD> <20><> <20><> <20>ִ<EFBFBD>.
|
|||
|
else
|
|||
|
{
|
|||
|
state = STATE_NORMAL;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
token += text[cur];
|
|||
|
}
|
|||
|
}
|
|||
|
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>尡 NORMAL <20><><EFBFBD><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>ְ<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><EFBFBD><EFBFBD> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
|
|||
|
else if (text[cur] == quote)
|
|||
|
{
|
|||
|
state = STATE_QUOTE;
|
|||
|
}
|
|||
|
// <20>ٸ<EFBFBD> <20>Ϲ<EFBFBD> <20><><EFBFBD>ڶ<EFBFBD><DAB6><EFBFBD> <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>Ѵ<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><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>δ<EFBFBD>. false<73><65> <20><><EFBFBD>쿡<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><EFBFBD> <20><><EFBFBD><EFBFBD>. <20>⺻<EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
|
|||
|
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><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>쿡<EFBFBD><ECBFA1> false
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const
|
|||
|
{
|
|||
|
Assert(seperator != quote);
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>忡 <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><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><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><EFBFBD> <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><EFBFBD> <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><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><EFBFBD> ','<27><> <20><>ū<EFBFBD><C5AB> <20>ڿ<EFBFBD><DABF><EFBFBD> <20>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
|||
|
if (j != row.size() - 1) { line += seperator; }
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
|||
|
file << line << std::endl;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// \brief <20><><EFBFBD><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><EFBFBD> <20><><EFBFBD><EFBFBD>. <20>⺻<EFBFBD><E2BABB><EFBFBD><EFBFBD> ','<27>̴<EFBFBD>.
|
|||
|
/// \param quote <20><><EFBFBD><EFBFBD>ǥ<EFBFBD><C7A5> <20><><EFBFBD><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><EFBFBD> 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><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>쿡<EFBFBD><ECBFA1> false<73><65> <20><>ȯ<EFBFBD>Ѵ<EFBFBD>.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
bool cCsvTable::Next()
|
|||
|
{
|
|||
|
// 20<32><30><EFBFBD><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><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>쿡<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>쿡<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];
|
|||
|
}
|
|||
|
|