Advertisement
Guest User

Untitled

a guest
Sep 22nd, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.85 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "CsvReader.h"
  3. #include <fstream>
  4. #include <algorithm>
  5.  
  6. #ifndef Assert
  7. #include <assert.h>
  8. #define Assert assert
  9. #define LogToFile (void)(0);
  10. #endif
  11.  
  12. namespace
  13. {
  14. /// ÆĽ̿ë state ¿­°Å°ª
  15. enum ParseState
  16. {
  17. STATE_NORMAL = 0, ///< ÀÏ¹Ý »óÅÂ
  18. STATE_QUOTE ///< µû¿ÈÇ¥ µÚÀÇ »óÅÂ
  19. };
  20.  
  21. /// ¹®ÀÚ¿­ Á¿ìÀÇ °ø¹éÀ» Á¦°ÅÇؼ­ ¹ÝȯÇÑ´Ù.
  22. std::string Trim(std::string str)
  23. {
  24. str = str.erase(str.find_last_not_of(" \t\r\n") + 1);
  25. str = str.erase(0, str.find_first_not_of(" \t\r\n"));
  26. return str;
  27. }
  28.  
  29. /// \brief ÁÖ¾îÁø ¹®Àå¿¡ ÀÖ´Â ¾ËÆĺªÀ» ¸ðµÎ ¼Ò¹®ÀÚ·Î ¹Ù²Û´Ù.
  30. std::string Lower(std::string original)
  31. {
  32. std::transform(original.begin(), original.end(), original.begin(), tolower);
  33. return original;
  34. }
  35. }
  36.  
  37. ////////////////////////////////////////////////////////////////////////////////
  38. /// \brief ¼¿À» ¾×¼¼½ºÇÒ ¶§, ¼ýÀÚ ´ë½Å »ç¿ëÇÒ À̸§À» µî·ÏÇÑ´Ù.
  39. /// \param name ¼¿ À̸§
  40. /// \param index ¼¿ À妽º
  41. ////////////////////////////////////////////////////////////////////////////////
  42. void cCsvAlias::AddAlias(const char* name, size_t index)
  43. {
  44. std::string converted(Lower(name));
  45.  
  46. Assert(m_Name2Index.find(converted) == m_Name2Index.end());
  47. Assert(m_Index2Name.find(index) == m_Index2Name.end());
  48.  
  49. m_Name2Index.insert(NAME2INDEX_MAP::value_type(converted, index));
  50. m_Index2Name.insert(INDEX2NAME_MAP::value_type(index, name));
  51. }
  52.  
  53. ////////////////////////////////////////////////////////////////////////////////
  54. /// \brief ¸ðµç µ¥ÀÌÅ͸¦ »èÁ¦ÇÑ´Ù.
  55. ////////////////////////////////////////////////////////////////////////////////
  56. void cCsvAlias::Destroy()
  57. {
  58. m_Name2Index.clear();
  59. m_Index2Name.clear();
  60. }
  61.  
  62. ////////////////////////////////////////////////////////////////////////////////
  63. /// \brief ¼ýÀÚ À妽º¸¦ À̸§À¸·Î º¯È¯ÇÑ´Ù.
  64. /// \param index ¼ýÀÚ À妽º
  65. /// \return const char* À̸§
  66. ////////////////////////////////////////////////////////////////////////////////
  67. const char* cCsvAlias::operator [] (size_t index) const
  68. {
  69. INDEX2NAME_MAP::const_iterator itr(m_Index2Name.find(index));
  70. if (itr == m_Index2Name.end())
  71. {
  72. LogToFile(NULL, "cannot find suitable conversion for %d", index);
  73. Assert(false && "cannot find suitable conversion");
  74. return NULL;
  75. }
  76.  
  77. return itr->second.c_str();
  78. }
  79.  
  80. ////////////////////////////////////////////////////////////////////////////////
  81. /// \brief À̸§À» ¼ýÀÚ À妽º·Î º¯È¯ÇÑ´Ù.
  82. /// \param name À̸§
  83. /// \return size_t ¼ýÀÚ À妽º
  84. ////////////////////////////////////////////////////////////////////////////////
  85. size_t cCsvAlias::operator [] (const char* name) const
  86. {
  87. NAME2INDEX_MAP::const_iterator itr(m_Name2Index.find(Lower(name)));
  88. if (itr == m_Name2Index.end())
  89. {
  90. LogToFile(NULL, "cannot find suitable conversion for %s", name);
  91. Assert(false && "cannot find suitable conversion");
  92. return 0;
  93. }
  94.  
  95. return itr->second;
  96. }
  97.  
  98. ////////////////////////////////////////////////////////////////////////////////
  99. /// \brief ÁöÁ¤µÈ À̸§ÀÇ CSV ÆÄÀÏÀ» ·ÎµåÇÑ´Ù.
  100. /// \param fileName CSV ÆÄÀÏ À̸§
  101. /// \param seperator ÇÊµå ºÐ¸®ÀÚ·Î »ç¿ëÇÒ ±ÛÀÚ. ±âº»°ªÀº ','ÀÌ´Ù.
  102. /// \param quote µû¿ÈÇ¥·Î »ç¿ëÇÒ ±ÛÀÚ. ±âº»°ªÀº '"'ÀÌ´Ù.
  103. /// \return bool ¹«»çÈ÷ ·ÎµåÇß´Ù¸é true, ¾Æ´Ï¶ó¸é false
  104. ////////////////////////////////////////////////////////////////////////////////
  105. bool cCsvFile::Load(const char* fileName, const char seperator, const char quote)
  106. {
  107. Assert(seperator != quote);
  108.  
  109. std::ifstream file(fileName, std::ios::in);
  110. if (!file) return false;
  111.  
  112. Destroy(); // ±âÁ¸ÀÇ µ¥ÀÌÅ͸¦ »èÁ¦
  113.  
  114. cCsvRow* row = NULL;
  115. ParseState state = STATE_NORMAL;
  116. std::string token = "";
  117. char buf[2048+1] = {0,};
  118.  
  119. while (file.good())
  120. {
  121. file.getline(buf, 2048);
  122. buf[sizeof(buf)-1] = 0;
  123.  
  124. std::string line(Trim(buf));
  125. if (line.empty() || (state == STATE_NORMAL && line[0] == '#')) continue;
  126.  
  127. std::string text = std::string(line) + " "; // ÆÄ½Ì lookahead ¶§¹®¿¡ ºÙ¿©ÁØ´Ù.
  128. size_t cur = 0;
  129.  
  130. while (cur < text.size())
  131. {
  132. // ÇöÀç ¸ðµå°¡ QUOTE ¸ðµåÀÏ ¶§,
  133. if (state == STATE_QUOTE)
  134. {
  135. // '"' ¹®ÀÚÀÇ Á¾·ù´Â µÎ °¡ÁöÀÌ´Ù.
  136. // 1. ¼¿ ³»ºÎ¿¡ Ư¼ö ¹®ÀÚ°¡ ÀÖÀ» °æ¿ì À̸¦ ¾Ë¸®´Â ¼¿ Á¿ìÀÇ °Í
  137. // 2. ¼¿ ³»ºÎÀÇ '"' ¹®ÀÚ°¡ '"' 2°³·Î ġȯµÈ °Í
  138. // ÀÌ Áß Ã¹¹ø° °æ¿ìÀÇ ÁÂÃø¿¡ ÀÖ´Â °ÍÀº CSV ÆÄÀÏÀÌ Á¤»óÀûÀ̶ó¸é,
  139. // ¹«Á¶°Ç STATE_NORMAL¿¡ °É¸®°Ô µÇ¾îÀÖ´Ù.
  140. // ±×·¯¹Ç·Î ¿©±â¼­ °É¸®´Â °ÍÀº 1¹øÀÇ ¿ìÃø °æ¿ì³ª, 2¹ø °æ¿ì »ÓÀÌ´Ù.
  141. // 2¹øÀÇ °æ¿ì¿¡´Â ¹«Á¶°Ç '"' ¹®ÀÚ°¡ 2°³¾¿ ³ªÅ¸³­´Ù. ÇÏÁö¸¸ 1¹øÀÇ
  142. // ¿ìÃø °æ¿ì¿¡´Â ¾Æ´Ï´Ù. À̸¦ ¹ÙÅÁÀ¸·Î Çؼ­ Äڵ带 Â¥¸é...
  143. if (text[cur] == quote)
  144. {
  145. // ´ÙÀ½ ¹®ÀÚ°¡ '"' ¹®ÀÚ¶ó¸é, Áï ¿¬¼ÓµÈ '"' ¹®ÀÚ¶ó¸é
  146. // ÀÌ´Â ¼¿ ³»ºÎÀÇ '"' ¹®ÀÚ°¡ ġȯµÈ °ÍÀÌ´Ù.
  147. if (text[cur+1] == quote)
  148. {
  149. token += quote;
  150. ++cur;
  151. }
  152. // ´ÙÀ½ ¹®ÀÚ°¡ '"' ¹®ÀÚ°¡ ¾Æ´Ï¶ó¸é
  153. // ÇöÀçÀÇ '"'¹®ÀÚ´Â ¼¿ÀÇ ³¡À» ¾Ë¸®´Â ¹®ÀÚ¶ó°í ÇÒ ¼ö ÀÖ´Ù.
  154. else
  155. {
  156. state = STATE_NORMAL;
  157. }
  158. }
  159. else
  160. {
  161. token += text[cur];
  162. }
  163. }
  164. // ÇöÀç ¸ðµå°¡ NORMAL ¸ðµåÀÏ ¶§,
  165. else if (state == STATE_NORMAL)
  166. {
  167. if (row == NULL)
  168. row = new cCsvRow();
  169.  
  170. // ',' ¹®ÀÚ¸¦ ¸¸³µ´Ù¸é ¼¿ÀÇ ³¡ÀÇ ÀǹÌÇÑ´Ù.
  171. // ÅäÅ«À¸·Î¼­ ¼¿ ¸®½ºÆ®¿¡´Ù°¡ Áý¾î³Ö°í, ÅäÅ«À» ÃʱâÈ­ÇÑ´Ù.
  172. if (text[cur] == seperator)
  173. {
  174. row->push_back(token);
  175. token.clear();
  176. }
  177. // '"' ¹®ÀÚ¸¦ ¸¸³µ´Ù¸é, QUOTE ¸ðµå·Î ÀüȯÇÑ´Ù.
  178. else if (text[cur] == quote)
  179. {
  180. state = STATE_QUOTE;
  181. }
  182. // ´Ù¸¥ ÀÏ¹Ý ¹®ÀÚ¶ó¸é ÇöÀç ÅäÅ«¿¡´Ù°¡ µ¡ºÙÀδÙ.
  183. else
  184. {
  185. token += text[cur];
  186. }
  187. }
  188.  
  189. ++cur;
  190. }
  191.  
  192. // ¸¶Áö¸· ¼¿Àº ³¡¿¡ ',' ¹®ÀÚ°¡ ¾ø±â ¶§¹®¿¡ ¿©±â¼­ Ãß°¡ÇØÁà¾ßÇÑ´Ù.
  193. // ´Ü, óÀ½¿¡ ÆÄ½Ì lookahead ¶§¹®¿¡ ºÙÀÎ ½ºÆäÀ̽º ¹®ÀÚ µÎ °³¸¦ ¶¾´Ù.
  194. if (state == STATE_NORMAL)
  195. {
  196. Assert(row != NULL);
  197. row->push_back(token.substr(0, token.size()-2));
  198. m_Rows.push_back(row);
  199. token.clear();
  200. row = NULL;
  201. }
  202. else
  203. {
  204. token = token.substr(0, token.size()-2) + "\r\n";
  205. }
  206. }
  207.  
  208. return true;
  209. }
  210.  
  211. ////////////////////////////////////////////////////////////////////////////////
  212. /// \brief °¡Áö°í ÀÖ´Â ³»¿ëÀ» CSV ÆÄÀÏ¿¡´Ù ÀúÀåÇÑ´Ù.
  213. /// \param fileName CSV ÆÄÀÏ À̸§
  214. /// \param append trueÀÏ °æ¿ì, ±âÁ¸ÀÇ ÆÄÀÏ¿¡´Ù µ¡ºÙÀδÙ. falseÀÎ °æ¿ì¿¡´Â
  215. /// ±âÁ¸ÀÇ ÆÄÀÏ ³»¿ëÀ» »èÁ¦ÇÏ°í, »õ·Î ¾´´Ù.
  216. /// \param seperator ÇÊµå ºÐ¸®ÀÚ·Î »ç¿ëÇÒ ±ÛÀÚ. ±âº»°ªÀº ','ÀÌ´Ù.
  217. /// \param quote µû¿ÈÇ¥·Î »ç¿ëÇÒ ±ÛÀÚ. ±âº»°ªÀº '"'ÀÌ´Ù.
  218. /// \return bool ¹«»çÈ÷ ÀúÀåÇß´Ù¸é true, ¿¡·¯°¡ »ý±ä °æ¿ì¿¡´Â false
  219. ////////////////////////////////////////////////////////////////////////////////
  220. bool cCsvFile::Save(const char* fileName, bool append, char seperator, char quote) const
  221. {
  222. Assert(seperator != quote);
  223.  
  224. // Ãâ·Â ¸ðµå¿¡ µû¶ó ÆÄÀÏÀ» Àû´çÇÑ Ç÷¡±×·Î »ý¼ºÇÑ´Ù.
  225. std::ofstream file;
  226. if (append) { file.open(fileName, std::ios::out | std::ios::app); }
  227. else { file.open(fileName, std::ios::out | std::ios::trunc); }
  228.  
  229. // ÆÄÀÏÀ» ¿­Áö ¸øÇß´Ù¸é, false¸¦ ¸®ÅÏÇÑ´Ù.
  230. if (!file) return false;
  231.  
  232. char special_chars[5] = { seperator, quote, '\r', '\n', 0 };
  233. char quote_escape_string[3] = { quote, quote, 0 };
  234.  
  235. // ¸ðµç ÇàÀ» Ⱦ´ÜÇϸ鼭...
  236. for (size_t i=0; i<m_Rows.size(); i++)
  237. {
  238. const cCsvRow& row = *((*this)[i]);
  239.  
  240. std::string line;
  241.  
  242. // Çà ¾ÈÀÇ ¸ðµç ÅäÅ«À» Ⱦ´ÜÇϸ鼭...
  243. for (size_t j=0; j<row.size(); j++)
  244. {
  245. const std::string& token = row[j];
  246.  
  247. // ÀϹÝÀûÀÎ('"' ¶Ç´Â ','¸¦ Æ÷ÇÔÇÏÁö ¾ÊÀº)
  248. // ÅäÅ«À̶ó¸é ±×³É ÀúÀåÇÏ¸é µÈ´Ù.
  249. if (token.find_first_of(special_chars) == std::string::npos)
  250. {
  251. line += token;
  252. }
  253. // Ư¼ö¹®ÀÚ¸¦ Æ÷ÇÔÇÑ ÅäÅ«À̶ó¸é ¹®ÀÚ¿­ Á¿쿡 '"'¸¦ ºÙ¿©ÁÖ°í,
  254. // ¹®ÀÚ¿­ ³»ºÎÀÇ '"'¸¦ µÎ °³·Î ¸¸µé¾îÁà¾ßÇÑ´Ù.
  255. else
  256. {
  257. line += quote;
  258.  
  259. for (size_t k=0; k<token.size(); k++)
  260. {
  261. if (token[k] == quote) line += quote_escape_string;
  262. else line += token[k];
  263. }
  264.  
  265. line += quote;
  266. }
  267.  
  268. // ¸¶Áö¸· ¼¿ÀÌ ¾Æ´Ï¶ó¸é ','¸¦ ÅäÅ«ÀÇ µÚ¿¡´Ù ºÙ¿©Áà¾ßÇÑ´Ù.
  269. if (j != row.size() - 1) { line += seperator; }
  270. }
  271.  
  272. // ¶óÀÎÀ» Ãâ·ÂÇÑ´Ù.
  273. file << line << std::endl;
  274. }
  275.  
  276. return true;
  277. }
  278.  
  279. ////////////////////////////////////////////////////////////////////////////////
  280. /// \brief ¸ðµç µ¥ÀÌÅ͸¦ ¸Þ¸ð¸®¿¡¼­ »èÁ¦ÇÑ´Ù.
  281. ////////////////////////////////////////////////////////////////////////////////
  282. void cCsvFile::Destroy()
  283. {
  284. for (ROWS::iterator itr(m_Rows.begin()); itr != m_Rows.end(); ++itr)
  285. delete *itr;
  286.  
  287. m_Rows.clear();
  288. }
  289.  
  290. ////////////////////////////////////////////////////////////////////////////////
  291. /// \brief ÇØ´çÇÏ´Â À妽ºÀÇ ÇàÀ» ¹ÝȯÇÑ´Ù.
  292. /// \param index À妽º
  293. /// \return cCsvRow* ÇØ´ç Çà
  294. ////////////////////////////////////////////////////////////////////////////////
  295. cCsvRow* cCsvFile::operator [] (size_t index)
  296. {
  297. Assert(index < m_Rows.size());
  298. return m_Rows[index];
  299. }
  300.  
  301. ////////////////////////////////////////////////////////////////////////////////
  302. /// \brief ÇØ´çÇÏ´Â À妽ºÀÇ ÇàÀ» ¹ÝȯÇÑ´Ù.
  303. /// \param index À妽º
  304. /// \return const cCsvRow* ÇØ´ç Çà
  305. ////////////////////////////////////////////////////////////////////////////////
  306. const cCsvRow* cCsvFile::operator [] (size_t index) const
  307. {
  308. Assert(index < m_Rows.size());
  309. return m_Rows[index];
  310. }
  311.  
  312. ////////////////////////////////////////////////////////////////////////////////
  313. /// \brief »ý¼ºÀÚ
  314. ////////////////////////////////////////////////////////////////////////////////
  315. cCsvTable::cCsvTable()
  316. : m_CurRow(-1)
  317. {
  318. }
  319.  
  320. ////////////////////////////////////////////////////////////////////////////////
  321. /// \brief ¼Ò¸êÀÚ
  322. ////////////////////////////////////////////////////////////////////////////////
  323. cCsvTable::~cCsvTable()
  324. {
  325. }
  326.  
  327. ////////////////////////////////////////////////////////////////////////////////
  328. /// \brief ÁöÁ¤µÈ À̸§ÀÇ CSV ÆÄÀÏÀ» ·ÎµåÇÑ´Ù.
  329. /// \param fileName CSV ÆÄÀÏ À̸§
  330. /// \param seperator ÇÊµå ºÐ¸®ÀÚ·Î »ç¿ëÇÒ ±ÛÀÚ. ±âº»°ªÀº ','ÀÌ´Ù.
  331. /// \param quote µû¿ÈÇ¥·Î »ç¿ëÇÒ ±ÛÀÚ. ±âº»°ªÀº '"'ÀÌ´Ù.
  332. /// \return bool ¹«»çÈ÷ ·ÎµåÇß´Ù¸é true, ¾Æ´Ï¶ó¸é false
  333. ////////////////////////////////////////////////////////////////////////////////
  334. bool cCsvTable::Load(const char* fileName, const char seperator, const char quote)
  335. {
  336. Destroy();
  337. return m_File.Load(fileName, seperator, quote);
  338. }
  339.  
  340. ////////////////////////////////////////////////////////////////////////////////
  341. /// \brief ´ÙÀ½ ÇàÀ¸·Î ³Ñ¾î°£´Ù.
  342. /// \return bool ´ÙÀ½ ÇàÀ¸·Î ¹«»çÈ÷ ³Ñ¾î°£ °æ¿ì true¸¦ ¹ÝȯÇÏ°í, ´õ ÀÌ»ó
  343. /// ³Ñ¾î°¥ ÇàÀÌ Á¸ÀçÇÏÁö ¾Ê´Â °æ¿ì¿¡´Â false¸¦ ¹ÝȯÇÑ´Ù.
  344. ////////////////////////////////////////////////////////////////////////////////
  345. bool cCsvTable::Next()
  346. {
  347. // 20¾ï¹ø Á¤µµ È£ÃâÇÏ¸é ¿À¹öÇ÷ΰ¡ ÀϾÅÙµ¥...±¦Âú°ÚÁö?
  348. return ++m_CurRow < (int)m_File.GetRowCount() ? true : false;
  349. }
  350.  
  351. ////////////////////////////////////////////////////////////////////////////////
  352. /// \brief ÇöÀç ÇàÀÇ ¼¿ ¼ýÀÚ¸¦ ¹ÝȯÇÑ´Ù.
  353. /// \return size_t ÇöÀç ÇàÀÇ ¼¿ ¼ýÀÚ
  354. ////////////////////////////////////////////////////////////////////////////////
  355. size_t cCsvTable::ColCount() const
  356. {
  357. return CurRow()->size();
  358. }
  359.  
  360. ////////////////////////////////////////////////////////////////////////////////
  361. /// \brief À妽º¸¦ ÀÌ¿ëÇØ int ÇüÀ¸·Î ¼¿ °ªÀ» ¹ÝȯÇÑ´Ù.
  362. /// \param index ¼¿ À妽º
  363. /// \return int ¼¿ °ª
  364. ////////////////////////////////////////////////////////////////////////////////
  365. int cCsvTable::AsInt(size_t index) const
  366. {
  367. const cCsvRow* const row = CurRow();
  368. Assert(row);
  369. Assert(index < row->size());
  370. return row->AsInt(index);
  371. }
  372.  
  373. ////////////////////////////////////////////////////////////////////////////////
  374. /// \brief À妽º¸¦ ÀÌ¿ëÇØ double ÇüÀ¸·Î ¼¿ °ªÀ» ¹ÝȯÇÑ´Ù.
  375. /// \param index ¼¿ À妽º
  376. /// \return double ¼¿ °ª
  377. ////////////////////////////////////////////////////////////////////////////////
  378. double cCsvTable::AsDouble(size_t index) const
  379. {
  380. const cCsvRow* const row = CurRow();
  381. Assert(row);
  382. Assert(index < row->size());
  383. return row->AsDouble(index);
  384. }
  385.  
  386. ////////////////////////////////////////////////////////////////////////////////
  387. /// \brief À妽º¸¦ ÀÌ¿ëÇØ std::string ÇüÀ¸·Î ¼¿ °ªÀ» ¹ÝȯÇÑ´Ù.
  388. /// \param index ¼¿ À妽º
  389. /// \return const char* ¼¿ °ª
  390. ////////////////////////////////////////////////////////////////////////////////
  391. const char* cCsvTable::AsStringByIndex(size_t index) const
  392. {
  393. const cCsvRow* const row = CurRow();
  394. Assert(row);
  395. Assert(index < row->size());
  396. return row->AsString(index);
  397. }
  398.  
  399. ////////////////////////////////////////////////////////////////////////////////
  400. /// \brief alias¸¦ Æ÷ÇÔÇØ ¸ðµç µ¥ÀÌÅ͸¦ »èÁ¦ÇÑ´Ù.
  401. ////////////////////////////////////////////////////////////////////////////////
  402. void cCsvTable::Destroy()
  403. {
  404. m_File.Destroy();
  405. m_Alias.Destroy();
  406. m_CurRow = -1;
  407. }
  408.  
  409. ////////////////////////////////////////////////////////////////////////////////
  410. /// \brief ÇöÀç ÇàÀ» ¹ÝȯÇÑ´Ù.
  411. /// \return const cCsvRow* ¾×¼¼½º°¡ °¡´ÉÇÑ ÇöÀç ÇàÀÌ Á¸ÀçÇÏ´Â °æ¿ì¿¡´Â ±× ÇàÀÇ
  412. /// Æ÷ÀÎÅ͸¦ ¹ÝȯÇÏ°í, ´õ ÀÌ»ó ¾×¼¼½º °¡´ÉÇÑ ÇàÀÌ ¾ø´Â °æ¿ì¿¡´Â NULLÀ»
  413. /// ¹ÝȯÇÑ´Ù.
  414. ////////////////////////////////////////////////////////////////////////////////
  415. const cCsvRow* const cCsvTable::CurRow() const
  416. {
  417. if (m_CurRow < 0)
  418. {
  419. Assert(false && "call Next() first!");
  420. return NULL;
  421. }
  422. else if (m_CurRow >= (int)m_File.GetRowCount())
  423. {
  424. Assert(false && "no more rows!");
  425. return NULL;
  426. }
  427.  
  428. return m_File[m_CurRow];
  429. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement