#ifndef __CSVFILE_H__ #define __CSVFILE_H__ #include #include #if _MSC_VER #include #else #include #endif //////////////////////////////////////////////////////////////////////////////// /// \class cCsvAlias /// \brief CSV ÆÄÀÏÀ» ¼öÁ¤ÇßÀ» ¶§ ¹ß»ýÇÏ´Â À妽º ¹®Á¦¸¦ ÁÙÀ̱â À§ÇÑ /// º°¸í °´Ã¼. /// /// ¿¹¸¦ µé¾î 0¹ø Ä÷³ÀÌ A¿¡ °üÇÑ ³»¿ëÀ» Æ÷ÇÔÇÏ°í, 1¹ø Ä÷³ÀÌ B¿¡ °üÇÑ ³»¿ëÀ» /// Æ÷ÇÔÇÏ°í ÀÖ¾ú´Âµ¥... /// ///
/// int a = row.AsInt(0);
/// int b = row.AsInt(1);
/// 
/// /// ±× »çÀÌ¿¡ C¿¡ °üÇÑ ³»¿ëÀ» Æ÷ÇÔÇÏ´Â Ä÷³ÀÌ ³¢¾îµç °æ¿ì, ÇϵåÄÚµùµÇ¾î ÀÖ´Â /// 1¹øÀ» ã¾Æ¼­ °íÃÄ¾ß Çϴµ¥, »ó´çÈ÷ ¿¡·¯°¡ ¹ß»ýÇϱ⠽¬¿î ÀÛ¾÷ÀÌ´Ù. /// ///
/// int a = row.AsInt(0);
/// int c = row.AsInt(1);
/// int b = row.AsInt(2); <-- ÀÌ ºÎºÐÀ» ÀÏÀÏÀÌ ½Å°æ½á¾ß ÇÑ´Ù.
/// 
/// /// ÀÌ ºÎºÐÀ» ¹®ÀÚ¿­·Î ó¸®Çϸé À¯Áöº¸¼ö¿¡ µé¾î°¡´Â ¼ö°í¸¦ ¾à°£À̳ª¸¶ ÁÙÀÏ ¼ö /// ÀÖ´Ù. //////////////////////////////////////////////////////////////////////////////// class cCsvAlias { private: #if _MSC_VER typedef stdext::hash_map NAME2INDEX_MAP; typedef stdext::hash_map INDEX2NAME_MAP; #else typedef std::map NAME2INDEX_MAP; typedef std::map INDEX2NAME_MAP; #endif NAME2INDEX_MAP m_Name2Index; ///< ¼¿ À妽º ´ë½ÅÀ¸·Î »ç¿ëÇϱâ À§ÇÑ À̸§µé INDEX2NAME_MAP m_Index2Name; ///< À߸øµÈ alias¸¦ °Ë»çÇϱâ À§ÇÑ Ãß°¡ÀûÀÎ ¸Ê public: /// \brief »ý¼ºÀÚ cCsvAlias() {} /// \brief ¼Ò¸êÀÚ virtual ~cCsvAlias() {} public: /// \brief ¼¿À» ¾×¼¼½ºÇÒ ¶§, ¼ýÀÚ ´ë½Å »ç¿ëÇÒ À̸§À» µî·ÏÇÑ´Ù. void AddAlias(const char* name, size_t index); /// \brief ¸ðµç µ¥ÀÌÅ͸¦ »èÁ¦ÇÑ´Ù. void Destroy(); /// \brief ¼ýÀÚ À妽º¸¦ À̸§À¸·Î º¯È¯ÇÑ´Ù. const char* operator [] (size_t index) const; /// \brief À̸§À» ¼ýÀÚ À妽º·Î º¯È¯ÇÑ´Ù. size_t operator [] (const char* name) const; private: /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö cCsvAlias(const cCsvAlias&) {} /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö const cCsvAlias& operator = (const cCsvAlias&) { return *this; } }; //////////////////////////////////////////////////////////////////////////////// /// \class cCsvRow /// \brief CSV ÆÄÀÏÀÇ ÇÑ ÇàÀ» ĸ½¶È­ÇÑ Å¬·¡½º /// /// CSVÀÇ ±âº» Æ÷¸ËÀº ¿¢¼¿¿¡¼­ º¸ÀÌ´Â ÇϳªÀÇ ¼¿À» ',' ¹®ÀÚ·Î ±¸ºÐÇÑ °ÍÀÌ´Ù. /// ÇÏÁö¸¸, ¼¿ ¾È¿¡ Ư¼ö ¹®ÀÚ·Î ¾²ÀÌ´Â ',' ¹®ÀÚ³ª '"' ¹®ÀÚ°¡ µé¾î°¥ °æ¿ì, /// ¸ð¾çÀÌ ¾à°£ ÀÌ»óÇÏ°Ô º¯ÇÑ´Ù. ´ÙÀ½Àº ±× º¯È­ÀÇ ¿¹ÀÌ´Ù. /// ///
/// ¿¢¼¿¿¡¼­ º¸ÀÌ´Â ¸ð¾ç | ½ÇÁ¦ CSV ÆÄÀÏ¿¡ µé¾î°¡ÀÖ´Â ¸ð¾ç
/// ---------------------+----------------------------------------------------
/// ItemPrice            | ItemPrice
/// Item,Price           | "Item,Price"
/// Item"Price           | "Item""Price"
/// "ItemPrice"          | """ItemPrice"""
/// "Item,Price"         | """Item,Price"""
/// Item",Price          | "Item"",Price"
/// 
/// /// ÀÌ ¿¹·Î¼­ ´ÙÀ½°ú °°Àº »çÇ×À» ¾Ë ¼ö ÀÖ´Ù. /// - ¼¿ ³»ºÎ¿¡ ',' ¶Ç´Â '"' ¹®ÀÚ°¡ µé¾î°¥ °æ¿ì, ¼¿ Á¿쿡 '"' ¹®ÀÚ°¡ »ý±ä´Ù. /// - ¼¿ ³»ºÎÀÇ '"' ¹®ÀÚ´Â 2°³·Î ġȯµÈ´Ù. /// /// \sa cCsvFile //////////////////////////////////////////////////////////////////////////////// class cCsvRow : public std::vector { public: /// \brief ±âº» »ý¼ºÀÚ cCsvRow() {} /// \brief ¼Ò¸êÀÚ ~cCsvRow() {} public: /// \brief ÇØ´ç ¼¿ÀÇ µ¥ÀÌÅ͸¦ int ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. int AsInt(size_t index) const { return atoi(at(index).c_str()); } /// \brief ÇØ´ç ¼¿ÀÇ µ¥ÀÌÅ͸¦ double ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. double AsDouble(size_t index) const { return atof(at(index).c_str()); } /// \brief ÇØ´ç ¼¿ÀÇ µ¥ÀÌÅ͸¦ ¹®ÀÚ¿­·Î ¹ÝȯÇÑ´Ù. const char* AsString(size_t index) const { return at(index).c_str(); } /// \brief ÇØ´çÇÏ´Â À̸§ÀÇ ¼¿ µ¥ÀÌÅ͸¦ int ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. int AsInt(const char* name, const cCsvAlias& alias) const { return atoi( at(alias[name]).c_str() ); } /// \brief ÇØ´çÇÏ´Â À̸§ÀÇ ¼¿ µ¥ÀÌÅ͸¦ int ÇüÀ¸·Î ¹ÝȯÇÑ´Ù. double AsDouble(const char* name, const cCsvAlias& alias) const { return atof( at(alias[name]).c_str() ); } /// \brief ÇØ´çÇÏ´Â À̸§ÀÇ ¼¿ µ¥ÀÌÅ͸¦ ¹®ÀÚ¿­·Î ¹ÝȯÇÑ´Ù. const char* AsString(const char* name, const cCsvAlias& alias) const { return at(alias[name]).c_str(); } private: /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö cCsvRow(const cCsvRow&) {} /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö const cCsvRow& operator = (const cCsvRow&) { return *this; } }; //////////////////////////////////////////////////////////////////////////////// /// \class cCsvFile /// \brief CSV(Comma Seperated Values) ÆÄÀÏÀ» read/writeÇϱâ À§ÇÑ Å¬·¡½º /// /// sample ///
/// cCsvFile file;
///
/// cCsvRow row1, row2, row3;
/// row1.push_back("ItemPrice");
/// row1.push_back("Item,Price");
/// row1.push_back("Item\"Price");
///
/// row2.reserve(3);
/// row2[0] = "\"ItemPrice\"";
/// row2[1] = "\"Item,Price\"";
/// row2[2] = "Item\",Price\"";
///
/// row3 = "\"ItemPrice\"\"Item,Price\"Item\",Price\"";
///
/// file.add(row1);
/// file.add(row2);
/// file.add(row3);
/// file.save("test.csv", false);
/// 
/// /// \todo ÆÄÀÏ¿¡¼­¸¸ ÀоîµéÀÏ °ÍÀÌ ¾Æ´Ï¶ó, ¸Þ¸ð¸® ¼Ò½º·ÎºÎÅÍ Àд ÇÔ¼öµµ /// ÀÖ¾î¾ß ÇÒ µí ÇÏ´Ù. //////////////////////////////////////////////////////////////////////////////// class cCsvFile { private: typedef std::vector ROWS; ROWS m_Rows; ///< Çà Ä÷º¼Ç public: /// \brief »ý¼ºÀÚ cCsvFile() {} /// \brief ¼Ò¸êÀÚ virtual ~cCsvFile() { Destroy(); } public: /// \brief ÁöÁ¤µÈ À̸§ÀÇ CSV ÆÄÀÏÀ» ·ÎµåÇÑ´Ù. bool Load(const char* fileName, const char seperator=',', const char quote='"'); /// \brief °¡Áö°í ÀÖ´Â ³»¿ëÀ» CSV ÆÄÀÏ¿¡´Ù ÀúÀåÇÑ´Ù. bool Save(const char* fileName, bool append=false, char seperator=',', char quote='"') const; /// \brief ¸ðµç µ¥ÀÌÅ͸¦ ¸Þ¸ð¸®¿¡¼­ »èÁ¦ÇÑ´Ù. void Destroy(); /// \brief ÇØ´çÇÏ´Â À妽ºÀÇ ÇàÀ» ¹ÝȯÇÑ´Ù. cCsvRow* operator [] (size_t index); /// \brief ÇØ´çÇÏ´Â À妽ºÀÇ ÇàÀ» ¹ÝȯÇÑ´Ù. const cCsvRow* operator [] (size_t index) const; /// \brief ÇàÀÇ °¹¼ö¸¦ ¹ÝȯÇÑ´Ù. size_t GetRowCount() const { return m_Rows.size(); } private: /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö cCsvFile(const cCsvFile&) {} /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö const cCsvFile& operator = (const cCsvFile&) { return *this; } }; //////////////////////////////////////////////////////////////////////////////// /// \class cCsvTable /// \brief CSV ÆÄÀÏÀ» ÀÌ¿ëÇØ Å×ÀÌºí µ¥ÀÌÅ͸¦ ·ÎµåÇÏ´Â °æ¿ì°¡ ¸¹Àºµ¥, ÀÌ Å¬·¡½º´Â /// ±× ÀÛ¾÷À» Á» ´õ ½±°Ô Çϱâ À§ÇØ ¸¸µç À¯Æ¿¸®Æ¼ Ŭ·¡½º´Ù. /// /// CSV ÆÄÀÏÀ» ·ÎµåÇÏ´Â °æ¿ì, ¼ýÀÚ¸¦ ÀÌ¿ëÇØ ¼¿À» ¾×¼¼½ºÇØ¾ß Çϴµ¥, CSV /// ÆÄÀÏÀÇ Æ÷¸ËÀÌ ¹Ù²î´Â °æ¿ì, ÀÌ ¼ýÀÚµéÀ» º¯°æÇØÁà¾ßÇÑ´Ù. ÀÌ ÀÛ¾÷ÀÌ ²Ï /// ½Å°æ ÁýÁßÀ» ¿ä±¸ÇÏ´Â µ¥´Ù°¡, ¿¡·¯°¡ ¹ß»ýÇϱ⠽±´Ù. ±×·¯¹Ç·Î ¼ýÀÚ·Î /// ¾×¼¼½ºÇϱ⺸´Ù´Â ¹®ÀÚ¿­·Î ¾×¼¼½ºÇÏ´Â °ÍÀÌ ¾à°£ ´À¸®Áö¸¸ ³´´Ù°í ÇÒ ¼ö ÀÖ´Ù. /// /// sample ///
/// cCsvTable table;
///
/// table.alias(0, "ItemClass");
/// table.alias(1, "ItemType");
///
/// if (table.load("test.csv"))
/// {
///     while (table.next())
///     {
///         std::string item_class = table.AsString("ItemClass");
///         int         item_type  = table.AsInt("ItemType"); 
///     }
/// }
/// 
//////////////////////////////////////////////////////////////////////////////// class cCsvTable { public : cCsvFile m_File; ///< CSV ÆÄÀÏ °´Ã¼ private: cCsvAlias m_Alias; ///< ¹®ÀÚ¿­À» ¼¿ À妽º·Î º¯È¯Çϱâ À§ÇÑ °´Ã¼ int m_CurRow; ///< ÇöÀç Ⱦ´Ü ÁßÀÎ Çà ¹øÈ£ public: /// \brief »ý¼ºÀÚ cCsvTable(); /// \brief ¼Ò¸êÀÚ virtual ~cCsvTable(); public: /// \brief ÁöÁ¤µÈ À̸§ÀÇ CSV ÆÄÀÏÀ» ·ÎµåÇÑ´Ù. bool Load(const char* fileName, const char seperator=',', const char quote='"'); /// \brief ¼¿À» ¾×¼¼½ºÇÒ ¶§, ¼ýÀÚ ´ë½Å »ç¿ëÇÒ À̸§À» µî·ÏÇÑ´Ù. void AddAlias(const char* name, size_t index) { m_Alias.AddAlias(name, index); } /// \brief ´ÙÀ½ ÇàÀ¸·Î ³Ñ¾î°£´Ù. bool Next(); /// \brief ÇöÀç ÇàÀÇ ¼¿ ¼ýÀÚ¸¦ ¹ÝȯÇÑ´Ù. size_t ColCount() const; /// \brief À妽º¸¦ ÀÌ¿ëÇØ int ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. int AsInt(size_t index) const; /// \brief À妽º¸¦ ÀÌ¿ëÇØ double ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. double AsDouble(size_t index) const; /// \brief À妽º¸¦ ÀÌ¿ëÇØ std::string ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. const char* AsStringByIndex(size_t index) const; /// \brief ¼¿ À̸§À» ÀÌ¿ëÇØ int ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. int AsInt(const char* name) const { return AsInt(m_Alias[name]); } /// \brief ¼¿ À̸§À» ÀÌ¿ëÇØ double ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. double AsDouble(const char* name) const { return AsDouble(m_Alias[name]); } /// \brief ¼¿ À̸§À» ÀÌ¿ëÇØ std::string ÇüÀ¸·Î ¼¿°ªÀ» ¹ÝȯÇÑ´Ù. const char* AsString(const char* name) const { return AsStringByIndex(m_Alias[name]); } /// \brief alias¸¦ Æ÷ÇÔÇØ ¸ðµç µ¥ÀÌÅ͸¦ »èÁ¦ÇÑ´Ù. void Destroy(); private: /// \brief ÇöÀç ÇàÀ» ¹ÝȯÇÑ´Ù. const cCsvRow* const CurRow() const; /// \brief º¹»ç »ý¼ºÀÚ ±ÝÁö cCsvTable(const cCsvTable&) {} /// \brief ´ëÀÔ ¿¬»êÀÚ ±ÝÁö const cCsvTable& operator = (const cCsvTable&) { return *this; } }; #endif //__CSVFILE_H__