在tiny C++通用库中,为了确保原始ini的正确性。windows API的又仅支持windows环境的。网络上又有大把ini的,但我觉得不够方便,就重写了一个。下面是ini的词法分析的实现:
///解析一行
template<class T>
XInt TXTIni<T>::ParseLine(const T & paramLine)
{
XInt iLength = paramLine.getLength();
XInt iPos = 0;
bool bSkipSpace = true;
T & strText = m_Temp;
strText.ToEmptyString();
m_ParseKey = m_ParseValue = m_ParseSection = m_ParseComment = strText;
m_ParseCommentPos = m_ParseKeyPos = m_ParseSectionPos = m_ParseValuePos = INI_INVALID_POS;
XInt iStatus = 0;
XInt iOldStatus = 0;
const char * p = paramLine.c_str();
while( iPos < iLength )
{
T::StringChar ch = paramLine[iPos];
if( bSkipSpace ) //跳过空格
{
if( isSpace(ch) )
{
iPos ++;
continue;
}
bSkipSpace = false;
}
switch(iStatus)
{
case 0:
{
if( isComment( ch ))
{
m_ParseComment = paramLine;
return EPTT_COMMENT;
}
else if( isSectionBegin(ch) )
{
iStatus = 1;
bSkipSpace = true;
}
else if( isEqual(ch) )
{
return EPTT_UNKNOW;
}
else
{
if( m_ParseKeyPos == INI_INVALID_POS) m_ParseKeyPos = iPos;
strText = ch;
iStatus = 2;
}
}
break;
case 1: //section
{
if( m_ParseSectionPos == INI_INVALID_POS ) m_ParseSectionPos = iPos;
if( isSectionEnd(ch) )
{
if( strText.isEmpty() )
{
return EPTT_UNKNOW;
}
else
{
strText.TrimRight(m_ParseSection);
strText.ToEmptyString();
bSkipSpace = true;
iStatus = 3;
}
}
strText += ch;
}
break;
case 2: //entry
{
if( isEqual(ch) )
{
if( strText.isEmpty() )
{
return EPTT_UNKNOW;
}
else
{
strText.TrimRight(m_ParseKey);
strText.ToEmptyString();
iStatus = 4;
bSkipSpace = true;
}
}
else
{
const char * k = strText.c_str();
strText += ch;
}
}
break;
case 3: //section 后段
{
if( isComment(ch))
{
m_ParseCommentPos = iPos;
paramLine.SubString(iPos,iLength - iPos, m_ParseComment); //读取注释
return EPTT_SECTION;
}
else
{
return EPTT_UNKNOW;
}
}
break;
case 4: //entry value
{
if( m_ParseValuePos == INI_INVALID_POS ) m_ParseValuePos = iPos;
if( ch == '#' || ch == ';' ) //如果直接读取注释
{
m_ParseCommentPos = iPos;
T::StringChar chPre = paramLine[iPos-1];
if( isSpace(chPre) )
{
strText.TrimRight(m_ParseValue);
strText.ToEmptyString();
paramLine.SubString(iPos,iLength-iPos,m_ParseComment);
return EPTT_ENTRY;
}
else if( strText.isEmpty())
{
paramLine.SubString(iPos,iLength-iPos,m_ParseComment);
return EPTT_ENTRY;
}
else //如果前面是非空格字符
{
strText += ch;
}
}
else
{
strText += ch;
}
}
break;
}
iPos ++;
}
switch(iStatus)
{
case 0:
return EPTT_SPACE;
case 1:
return EPTT_UNKNOW;
case 2:
return EPTT_UNKNOW;
case 3:
return EPTT_SECTION;
case 4:
strText.TrimRight(m_ParseValue);
return EPTT_ENTRY;
}
return EPTT_UNKNOW;
}