/*********************************************************************
Copyright (C) 2001 by
Alexander Berthold, alexander-berthold@web.de.
Hoegestr. 54
79108 Freiburg i. Breisgau
Germany
-- This file is part of cxTokenizer --
"cxTokenizer" is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or any later version.
"cxTokenizer" is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with "cxTokenizer"; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
---------------------------------------------------------------
If you find any bugs or if you make other corrections/
enhancements, i'd appreciate if you'd let me know about
that. My email is
alexander-berthold@web.de
If you share this code, do not remove this text.
---------------------------------------------------------------
Class: cxTokenizerInputStream
Author: Alexander Berthold
Copyright: Alexander Berthold
Date: 2001/06/12
Version: 0.1.16
Purpose: Base class for the input stream for the lexxer.
Must support 'ctkExternalObjectPointer'.
See 'cxTokenizerTextInputStream' for an application.
Version history:
- 2001/05/19
Renamed class from 'cpLexxerInputStream' to 'cxTokenizerInputStream'.
- 2001/06/05
Current source labeled version 0.1.15
- 2001/06/08
Added method (fGetCurrentLine) to get the current line.
Also intruduced 'fReadBlock' to randomly read within the input stream.
Must not be supported by derived classes; but if it isn't supported,
'fGetCurrentLine' won't work.
- 2001/06/12
Fixed some problems + added some methods for conveniently (if implemented
by the derived class) getting line number information.
New version number is now 0.1.16
*********************************************************************/
// cxTokenizerInputStream.h: interface for the cxTokenizerInputStream class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_CXTOKENIZERINPUTSTREAM_H__2EEE2883_3AE8_42FD_9387_38FF266EAD49__INCLUDED_)
#define AFX_CXTOKENIZERINPUTSTREAM_H__2EEE2883_3AE8_42FD_9387_38FF266EAD49__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
enum {
crlf_cronly=0,
crlf_lfonly=1,
crlf_crlf=2
};
class cxTokenizerInputStream :
public ctkExternalObjectPointer,
public ctkCheckValid
{
// Construction
public:
cxTokenizerInputStream()
{};
virtual ~cxTokenizerInputStream()
{};
// Attributes
protected:
// Protected operations
protected:
virtual bool fReadBlock(long lStartPos, long lLength, std::tstring& strResult, TCHAR tcTermChar) const
{ return false; };
// Operations
public:
virtual TCHAR tcGetNextCharacter() = 0;
virtual bool fPutBack(LPCTSTR lpszText) = 0;
virtual bool fPutBack(TCHAR tcChar) = 0;
virtual bool fIsEofReached() const = 0;
virtual void vInit() {};
virtual long lGetCurrentLine() const = 0;
virtual long lGetCurrentPosition() const = 0;
virtual long lGetCurrentPosInLine() const = 0;
virtual bool fGetCurrentLine(std::tstring& strResult) const = 0;
virtual bool fGetLineAtPosition(long lPosition, std::tstring& strResult) const = 0;
virtual long lGetLineNumberFromPosition(long lPosition) const = 0;
virtual long lGetPositionFromLineNumber(long lLineNumber) const = 0;
long lGetPosInLine(long lPosition) const
{
long lLine = lGetLineNumberFromPosition(lPosition);
long lStartPos;
if(lLine==-1) return -1;
lStartPos = lGetPositionFromLineNumber(lLine);
if(lStartPos==-1) return -1;
return lPosition-lStartPos;
}
};
template<int t_nMode, bool t_fUseLNCallback = false>
class cxTokenizerInputStreamDefaultImpl :
public cxTokenizerInputStream
{
// Construction/Destruction
public:
cxTokenizerInputStreamDefaultImpl()
{
m_nCurrentLine =0;
m_nCurPosInLine =0;
m_nCurPosInStream=0;
m_nCurLineStartPos=0;
}
// Attributes
protected:
int m_nCurrentLine;
int m_nCurPosInLine;
int m_nCurPosInStream;
int m_nCurLineStartPos;
// Protected callback operations
protected:
virtual void vLineNumberReached(long lLineNumber, long lPosition)
{ return; };
// Operations
public:
TCHAR tcGetNextCharacterDefaultImpl(TCHAR tcChar)
{
bool fNewLine = false;
if(t_nMode==crlf_cronly && tcChar=='\x0d')
fNewLine = true;
if(t_nMode==crlf_lfonly && tcChar=='\x0a')
fNewLine = true;
if(fNewLine)
{
m_nCurrentLine++;
m_nCurPosInLine=0;
m_nCurLineStartPos=lGetCurrentPosition()+1;
if(t_fUseLNCallback)
vLineNumberReached(m_nCurrentLine,m_nCurLineStartPos);
}
else
{
if(m_nCurPosInLine!=-1)
m_nCurPosInLine++;
}
m_nCurPosInStream++;
return tcChar;
}
bool fPutBackDefaultImpl(LPCTSTR lpszText)
{
TCHAR tcChar;
while( (tcChar=(*(lpszText++)))!='\0' )
{
m_nCurPosInStream--;
if(t_nMode==crlf_cronly && tcChar=='\x0d')
m_nCurrentLine--, m_nCurPosInLine=-1, m_nCurLineStartPos=lGetCurrentPosition();
if(t_nMode==crlf_lfonly && tcChar=='\x0a')
m_nCurrentLine--, m_nCurPosInLine=-1, m_nCurLineStartPos=lGetCurrentPosition();
}
return true;
}
bool fPutBackDefaultImpl(TCHAR tcChar)
{
m_nCurPosInStream--;
if(t_nMode==crlf_cronly && tcChar=='\x0d')
m_nCurrentLine--, m_nCurPosInLine=-1, m_nCurLineStartPos=lGetCurrentPosition();
if(t_nMode==crlf_lfonly && tcChar=='\x0a')
m_nCurrentLine--, m_nCurPosInLine=-1, m_nCurLineStartPos=lGetCurrentPosition();
return true;
}
virtual long lGetCurrentLine() const { return m_nCurrentLine; };
virtual long lGetCurrentPosition() const { return m_nCurPosInStream; };
virtual long lGetCurrentPosInLine() const { return m_nCurPosInLine; };
virtual bool fGetCurrentLine(std::tstring& strResult) const
{
if(t_nMode==crlf_cronly)
return fReadBlock(m_nCurLineStartPos,512,strResult,_T('\x0d'));
if(t_nMode==crlf_lfonly)
return fReadBlock(m_nCurLineStartPos,512,strResult,_T('\x0a'));
return false;
}
virtual bool fGetLineAtPosition(long lPosition, std::tstring& strResult) const
{ return false; };
virtual long lGetLineNumberFromPosition(long lPosition) const
{ return -1; };
virtual long lGetPositionFromLineNumber(long lLineNumber) const
{ return -1; };
};
template<int t_nMode>
class cxTokenizerInputStreamDefaultWithLineNumberImpl :
public cxTokenizerInputStreamDefaultImpl<t_nMode,true>
{
// Attributes
public:
typedef std::map<long,long> L2L_map_type;
L2L_map_type m_mapLNToPosition;
L2L_map_type m_mapPositionToLN;
// Protected callback operations
protected:
virtual void vLineNumberReached(long lLineNumber, long lPosition)
{
m_mapLNToPosition.insert(L2L_map_type::value_type(lLineNumber,lPosition));
m_mapPositionToLN.insert(L2L_map_type::value_type(lPosition,lLineNumber));
return;
};
// Operations
public:
virtual void vInit()
{
vLineNumberReached(0,0);
}
virtual bool fGetLineAtPosition(long lPosition, std::tstring& strResult) const
{
long lLineNumber = lGetLineNumberFromPosition(lPosition);
long lStartPos = -1;
L2L_map_type::const_iterator it;
if(lLineNumber==-1)
return false;
it =m_mapLNToPosition.find(lLineNumber);
ASSERT(it!=m_mapLNToPosition.end());
if(it==m_mapLNToPosition.end())
return false;
lStartPos =it->second;
if(t_nMode==crlf_cronly)
return fReadBlock(lStartPos,512,strResult,_T('\x0d'));
if(t_nMode==crlf_lfonly)
return fReadBlock(lStartPos,512,strResult,_T('\x0a'));
return false;
};
virtual long lGetLineNumberFromPosition(long lPosition) const
{
L2L_map_type::const_iterator it;
long lLineNumber = -1;
it =m_mapPositionToLN.begin();
// @ToDo:
// Could be improved by a binary search or something,
// but as this method should only be called when a parsing error
// happened, it shouldn't be time critical.
while(it!=m_mapPositionToLN.end())
{
if(it->first>lPosition)
break;
lLineNumber =it->second;
it++;
}
return lLineNumber;
};
virtual long lGetPositionFromLineNumber(long lLineNumber) const
{
L2L_map_type::const_iterator it;
it =m_mapLNToPosition.find(lLineNumber);
if(it==m_mapLNToPosition.end())
return -1;
return it->second;
};
};
#endif // !defined(AFX_CXTOKENIZERINPUTSTREAM_H__2EEE2883_3AE8_42FD_9387_38FF266EAD49__INCLUDED_)