239 lines
5.5 KiB
C++
239 lines
5.5 KiB
C++
|
|
#include "Config.h"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <boost/algorithm/string.hpp> // use boost
|
|
|
|
|
|
Config::Config()
|
|
: m_keyDelimiter( CONFIG_DEFAULT_KEY_DELIMITER )
|
|
, m_valueDelimiter( CONFIG_DEFAULT_VALUE_DELIMITER )
|
|
{
|
|
|
|
}
|
|
|
|
/// @brief destructor
|
|
Config::~Config()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
/// @brief 지정된 Config 파일의 모든 정보를 읽어 내부 변수에 저장처리
|
|
/// @param path [in] Config file 의 전체 경로정보( C 배열 지원을 위해 & 사용안함)
|
|
/// @return On success return true, otherwise return false
|
|
bool Config::Open( const string path )
|
|
{
|
|
ifstream file;
|
|
|
|
// Config file open
|
|
file.open( path.c_str());
|
|
if( file.is_open() == false )
|
|
{
|
|
cerr << "[error] " << __FILE__<< ":" << __func__ << ": config file open failed.[" << path << "][" << strerror( errno ) << "]" << endl;
|
|
return false;
|
|
}
|
|
|
|
// 기존 데이터가 존재하면 삭제 처리.
|
|
if( m_configData.empty() == false )
|
|
m_configData.clear();
|
|
|
|
// config file parsing
|
|
string line;
|
|
string section;
|
|
vector< string > configs;
|
|
|
|
// 루프를 돌면서 Config 파일을 line 단위로 읽어들인당....
|
|
while( std::getline( file, line ) )
|
|
{
|
|
// 앞뒤 공백 제거 처리
|
|
boost::trim( line );
|
|
|
|
// 공백 or 주석처리 라인 검사
|
|
if( line.empty() == true || boost::starts_with( line, string("#") ) == true || line == "\r" )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Section 여부 검사
|
|
if( boost::starts_with( line, string("[") ) == true && boost::ends_with( line, string("]") ) == true )
|
|
{
|
|
// [] 로 정의된 section 의 문자열 값 추출
|
|
line.erase( line.begin() );
|
|
line.erase( line.end() -1 );
|
|
boost::trim( line );
|
|
|
|
if( section.empty() == false && section != line )
|
|
{
|
|
// 이전 세션과 다른 신규 세션인 경우
|
|
// 기존까지 저장했던 데이터를 멤버 변수에 입력 처리 후 내부변수 초기화 처리.
|
|
|
|
m_configData.insert( make_pair( section, configs ) );
|
|
section.clear();
|
|
configs.clear();
|
|
}
|
|
|
|
// 신규 section 정보 저장처리.
|
|
section = line;
|
|
line.clear();
|
|
}
|
|
else
|
|
{
|
|
// Section 정보가 아닌 경우 => 실제 설정값 .. ^^
|
|
configs.push_back( line );
|
|
}
|
|
}
|
|
|
|
// 마지막 세션 처리된 정보가 존재하는 경우 멤버 변수에 저장 처리.
|
|
if( section.empty() == false )
|
|
{
|
|
m_configData.insert( make_pair( section, configs ) );
|
|
}
|
|
|
|
// 종료 처리.
|
|
file.close();
|
|
return true;
|
|
}
|
|
|
|
/// @brief Config 멤버 변수에 저장된 데이터 삭제처리.
|
|
/// @return void
|
|
void Config::Clear()
|
|
{
|
|
m_configData.clear();
|
|
}
|
|
|
|
/// @brief 해당 Section, Key 에 해당하는 value 값을 찾아 반환
|
|
/// @param section [in] 찾고자 하는 Section 값
|
|
/// @param key [in] 찾고자 하는 key 값
|
|
/// @param value [out] 해당 Section, Key 에 해당하는 value 값을 저장하기 위한 변수
|
|
/// @return On success return true, otherwise return false
|
|
bool Config::GetConfig( const string& section, const string& key, string& value )
|
|
{
|
|
// Section 에 대한 임시 데이터 저장객체 생성
|
|
vector< string > configs;
|
|
|
|
// 해당 Section 이 존재하지 않는 경우
|
|
if( Find( section, configs ) == false )
|
|
return false;
|
|
|
|
string line;
|
|
string result;
|
|
vector< string >::const_iterator it;
|
|
|
|
// 해당 Key 이 존재하는지 검사
|
|
for( it = configs.begin(); it != configs.end(); it++)
|
|
{
|
|
line = *it;
|
|
|
|
// Line 상의 주석 제거
|
|
string::size_type pos = line.find( '#' );
|
|
if( pos != string::npos)
|
|
{
|
|
line = line.substr(0, pos);
|
|
boost::trim( line );
|
|
}
|
|
|
|
// key = value 에서 key 부분 추출
|
|
pos = line.find( m_keyDelimiter );
|
|
if( pos == string::npos )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
result = line.substr(0, pos);
|
|
boost::trim( result );
|
|
}
|
|
|
|
if( key == result )
|
|
{
|
|
// Key 값이 동일한 경우
|
|
value = line.substr( pos+1 );
|
|
boost::trim( value );
|
|
// ${value} : 참조 값 찾기
|
|
pos = value.find( "${" );
|
|
if( pos != string::npos )
|
|
{
|
|
value = value.substr(pos+2);
|
|
pos = value.rfind("}");
|
|
if( pos != string::npos )
|
|
{
|
|
value = value.substr(0,pos);
|
|
pos = value.find( '.' );
|
|
if( pos != string::npos )
|
|
{
|
|
string ss = value.substr(0,pos);
|
|
string kk = value.substr(pos+1);
|
|
return GetConfig( ss, kk,value );
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// @brief 해당 Section, Key 에 해당하는 value Array 값을 찾아 반환
|
|
/// @param section [in] 찾고자 하는 Section 값
|
|
/// @param key [in] 찾고자 하는 key 값
|
|
/// @param value [out] 해당 Section, Key 에 해당하는 value 값을 저장하기 위한 배열
|
|
/// @return On success return true, otherwise return false
|
|
bool Config::GetConfig( const string& section, const string& key, vector< string >& value )
|
|
{
|
|
string result;
|
|
vector< string > vec;
|
|
|
|
if( GetConfig( section, key, result ) == false )
|
|
return false;
|
|
|
|
// 전달받은 result 값을 value delimiter 를 이용하여 parsing 처리
|
|
boost::split( vec, result, boost::is_any_of( m_valueDelimiter ));
|
|
if( vec.empty() == true )
|
|
return false;
|
|
|
|
// 루프를 돌면서 trim 처리 후 결과값 저장처리.
|
|
vector< string >::const_iterator it;
|
|
for( it = vec.begin(); it != vec.end(); it++)
|
|
{
|
|
result = boost::trim_copy( *it );
|
|
|
|
if( result.empty() == false )
|
|
value.push_back( result );
|
|
}
|
|
|
|
if( value.empty() == true )
|
|
return false;
|
|
else
|
|
return true;
|
|
}
|
|
|
|
/// @brief Config 멤버 변수에 저장된 데이터 중 해당 Section 에 해당하는 데이터 반환.
|
|
/// @param section [in] section 명
|
|
/// @param configData [out] 해당 Section 에서 읽은 Cofig 정보를 저장할 string 배열
|
|
/// @return On success return true, otherwise return false
|
|
bool Config::Find( const string& section, vector<string>& configData )
|
|
{
|
|
map< string, vector< string > >::iterator it = m_configData.find( section );
|
|
if( it != m_configData.end() )
|
|
{
|
|
// 해당 section 을 찾은 경우
|
|
configData = it->second;
|
|
return true;
|
|
}
|
|
|
|
// 해당 section 을 찾지 못한 경우
|
|
return false;
|
|
}
|
|
|
|
|