server/game/src/group_text_parse_tree.h

235 lines
6.1 KiB
C++

#ifndef __INC_METIN_II_GROUP_TEXT_PARSE_TREE_H__
#define __INC_METIN_II_GROUP_TEXT_PARSE_TREE_H__
#include <common/d3dtype.h>
#include <common/pool.h>
#include "file_loader.h"
#include <sstream>
typedef std::map<std::string, TTokenVector> TTokenVectorMap;
typedef std::map<std::string, int> TMapNameToIndex;
class CGroupNode
{
public:
class CGroupNodeRow
{
public:
CGroupNodeRow(CGroupNode* pGroupNode, TTokenVector& vec_values);
virtual ~CGroupNodeRow();
template <typename T>
bool GetValue(const std::string & stColKey, OUT T& value) const;
template <typename T>
bool GetValue(int idx, OUT T& value) const;
int GetSize() const;
private:
CGroupNode* m_pOwnerGroupNode;
TTokenVector m_vec_values;
};
public:
CGroupNode();
virtual ~CGroupNode();
bool Load(const char * c_szFileName);
const char * GetFileName();
DWORD GetChildNodeCount();
bool SetChildNode(const char * c_szKey, CGroupNode* pChildNode);
CGroupNode* GetChildNode(const std::string & c_rstrKey) const;
std::string GetNodeName() const;
bool IsToken(const std::string & c_rstrKey) const;
int GetRowCount();
template <typename T>
bool GetValue(size_t i, const std::string & c_rstrColKey, T& tValue) const; // n번째(map에 들어있는 순서일 뿐, txt의 순서와는 관계 없음) row의 특정 컬럼의 값을 반환하는 함수.
// 이질적이긴 하지만, 편의를 위한 함수.
template <typename T>
bool GetValue(const std::string & c_rstrRowKey, const std::string & c_rstrColKey, T& tValue) const;
template <typename T>
bool GetValue(const std::string & c_rstrRowKey, int index, T& tValue) const;
bool GetRow(const std::string & c_rstrKey, OUT const CGroupNodeRow ** ppRow) const;
// 참고로, idx랑 txt에 쓰여진 순서랑 관계 없음.
bool GetRow(int idx, OUT const CGroupNodeRow ** ppRow) const;
bool GetGroupRow(const std::string& stGroupName, const std::string& stRow, OUT const CGroupNode::CGroupNodeRow ** ppRow) const;
template <typename T>
bool GetGroupValue(const std::string& stGroupName, const std::string& stRow, int iCol, OUT T& tValue) const;
template <typename T>
bool GetGroupValue(const std::string& stGroupName, const std::string& stRow, const std::string& stCol, OUT T& tValue) const;
int GetColumnIndexFromName(const std::string& stName) const;
private:
typedef std::map <std::string, CGroupNode*> TMapGroup;
typedef std::map <std::string, CGroupNode::CGroupNodeRow> TMapRow;
TMapGroup m_mapChildNodes;
std::string strGroupName;
TMapNameToIndex m_map_columnNameToIndex;
TMapRow m_map_rows;
friend class CGroupTextParseTreeLoader;
};
class CGroupTextParseTreeLoader
{
public:
CGroupTextParseTreeLoader();
virtual ~CGroupTextParseTreeLoader();
bool Load(const char * c_szFileName);
const char * GetFileName();
CGroupNode* GetGroup(const char * c_szGroupName);
private:
bool LoadGroup(CGroupNode * pGroupNode);
CGroupNode * m_pRootGroupNode;
std::string m_strFileName;
DWORD m_dwcurLineIndex;
CMemoryTextFileLoader m_fileLoader;
};
template <typename T>
bool from_string(OUT T& t, IN const std::string& s)
{
std::istringstream iss(s);
return !(iss >> t).fail();
}
template <>
inline bool from_string <BYTE>(OUT BYTE& t, IN const std::string& s)
{
std::istringstream iss(s);
int temp;
bool b = !(iss >> temp).fail();
t = (BYTE)temp;
return b;
}
template <typename T>
bool CGroupNode::GetValue(size_t i, const std::string & c_rstrColKey, T& tValue) const
{
if (i > m_map_rows.size())
return false;
TMapRow::const_iterator row_it = m_map_rows.begin();
std::advance(row_it, i);
itertype(m_map_columnNameToIndex) col_idx_it = m_map_columnNameToIndex.find(c_rstrColKey);
if (m_map_columnNameToIndex.end() == col_idx_it)
{
return false;
}
int index = col_idx_it->second;
if (row_it->second.GetSize() <= index)
{
return false;
}
return row_it->second.GetValue(index, tValue);
}
template <typename T>
bool CGroupNode::GetValue(const std::string & c_rstrRowKey, const std::string & c_rstrColKey, T& tValue) const
{
TMapRow::const_iterator row_it = m_map_rows.find(c_rstrRowKey);
if (m_map_rows.end() == row_it)
{
return false;
}
itertype(m_map_columnNameToIndex) col_idx_it = m_map_columnNameToIndex.find(c_rstrColKey);
if (m_map_columnNameToIndex.end() == col_idx_it)
{
return false;
}
int index = col_idx_it->second;
if (row_it->second.GetSize() <= index)
{
return false;
}
return row_it->second.GetValue(index, tValue);
}
template <typename T>
bool CGroupNode::GetValue(const std::string & c_rstrRowKey, int index, T& tValue) const
{
TMapRow::const_iterator row_it = m_map_rows.find(c_rstrRowKey);
if (m_map_rows.end() == row_it)
{
return false;
}
if (row_it->second.GetSize() <= index)
{
return false;
}
return row_it->second.GetValue(index, tValue);
}
template <typename T>
bool CGroupNode::GetGroupValue(const std::string& stGroupName, const std::string& stRow, int iCol, OUT T& tValue) const
{
CGroupNode* pChildGroup = GetChildNode(stGroupName);
if (NULL != pChildGroup)
{
if (pChildGroup->GetValue(stRow, iCol, tValue))
return true;
}
// default group을 살펴봄.
pChildGroup = GetChildNode("default");
if (NULL != pChildGroup)
{
if (pChildGroup->GetValue(stRow, iCol, tValue))
return true;
}
return false;
}
template <typename T>
bool CGroupNode::GetGroupValue(const std::string& stGroupName, const std::string& stRow, const std::string& stCol, OUT T& tValue) const
{
CGroupNode* pChildGroup = GetChildNode(stGroupName);
if (NULL != pChildGroup)
{
if (pChildGroup->GetValue(stRow, stCol, tValue))
return true;
}
// default group을 살펴봄.
pChildGroup = GetChildNode("default");
if (NULL != pChildGroup)
{
if (pChildGroup->GetValue(stRow, stCol, tValue))
return true;
}
return false;
}
template <typename T>
bool CGroupNode::CGroupNodeRow::GetValue(const std::string & stColKey, OUT T& value) const
{
int idx = m_pOwnerGroupNode->GetColumnIndexFromName(stColKey);
if (idx < 0 || idx >= m_vec_values.size())
return false;
return from_string(value, m_vec_values[idx]);
}
template <typename T>
bool CGroupNode::CGroupNodeRow::GetValue(int idx, OUT T& value) const
{
if (idx < 0 || idx >= m_vec_values.size())
return false;
return from_string(value, m_vec_values[idx]);
}
#endif