/*********************************************************************
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.
---------------------------------------------------------------
*********************************************************************/
// cxTokenizerStringTokenRule.cpp: implementation of the cxTokenizerStringTokenRule class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "cxTokenizerTokenRule.h"
#include "cxTokenizerContextCookie.h"
#include "cxTokenizerContext.h"
#include "cxTokenizerStringTokenRule.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
cxTokenizerStringTokenRule::cxTokenizerStringTokenRule(int nIDValue, xttr_flags ttrf, const std::tstring& strInitString)
: cxTokenizerTokenRule(nIDValue, ttrf,NULL,strInitString)
{
}
cxTokenizerStringTokenRule::~cxTokenizerStringTokenRule()
{
}
//////////////////////////////////////////////////////////////////////
// Operations
//////////////////////////////////////////////////////////////////////
bool cxTokenizerStringTokenRule::fDoesApply(
const cxTokenizerContext *ptcContext,
TCHAR tcChar, bool *pfComplete,
int nStartPos, int nCurPos) const
{
const cxTokenizerStringContextCookie
*pCookie = NULL;
ptcContext->fGetConstCookie(this,&pCookie);
if(nCurPos==nStartPos)
{
if(tcChar=='"')
{
if(pCookie!=NULL)
{
// This is the case when the end of a quoted section is found:
// "hello"
// ^ here this happens.
// So it must be ignored
return false;
}
return true;
}
else
return false;
}
ASSERT(pCookie!=NULL);
if(pCookie->fCompleted)
return false;
if(pCookie->fInEscape)
return true;
if(tcChar=='"')
{
(*pfComplete)=true;
return true;
}
return true;
}
void cxTokenizerStringTokenRule::vApplied(
cxTokenizerContext *ptcContext,
TCHAR tcChar,
bool /* fCompleted */,
int nStartPos, int nCurPos) const
{
cxTokenizerStringContextCookie
*pCookie = NULL;
ptcContext->fGetCookie(this,&pCookie);
// First character?
if(nCurPos==nStartPos)
{
if(tcChar=='"' && pCookie==NULL)
{
// We need exclusive access to the following characters:
ptcContext->vSetFlag(tctx_exclusive,true);
ASSERT(pCookie==NULL);
ptcContext->fSetCookie(this,&pCookie);
ASSERT(pCookie!=NULL);
return;
}
else
return;
}
// No, cookie must already exist.
ASSERT(pCookie!=NULL);
if(pCookie->fCompleted)
return;
TCHAR tcCharToAdd = _T('\0');
// In escape sequence?
if(!pCookie->fInEscape)
{
// No.
if(tcChar=='\\')
{
// Start escape sequence
pCookie->fInEscape =true;
pCookie->esct =esc_begin;
}
else
{
// End of quotation?
if(tcChar=='\"')
{
// Release exclusive access
ptcContext->vSetFlag(tctx_exclusive,false);
// Set completed flag
pCookie->fCompleted=true;
return;
}
// Otherwise, 'tcChar' must be added to result
tcCharToAdd=tcChar;
}
}
else
{
// Yes, escape sequence
// First character after '\'?
if(pCookie->esct==esc_begin)
{
// Yes.
switch(tcChar)
{
case '\\':
case '\"':
case '\'':
case '\?':
tcCharToAdd=tcChar;
pCookie->fInEscape=false;
break;
/* case isdigit(tcChar):
pCookie->strEsc=tcChar;
pCookie->esct=esc_octal;
break;*/
case 'n':
tcCharToAdd='\n';
pCookie->fInEscape=false;
break;
case 'x':
pCookie->strEsc=_T("");
pCookie->esct=esc_hex;
break;
default:
pCookie->fInEscape=false;
throw cxTokenizerException(LEXERR_INVALID_ESCAPE_SEQUENCE);
break;
}
}
else
{
// No
if(pCookie->esct==esc_octal)
ASSERT(FALSE);
if(pCookie->esct==esc_hex)
{
pCookie->strEsc+=tcChar;
if(pCookie->strEsc.length()==2)
{
tcCharToAdd =(TCHAR)_tcstoul(pCookie->strEsc.data(),NULL,16);
pCookie->fInEscape=false;
}
}
}
}
if(tcCharToAdd!=_T('\0'))
pCookie->strResult+=tcCharToAdd;
}
bool cxTokenizerStringTokenRule::fGetResultString(const cxTokenizerContext* ptcContext, std::tstring& strResult) const
{
const cxTokenizerStringContextCookie
*pCookie = NULL;
ptcContext->fGetConstCookie(this,&pCookie);
ASSERT(pCookie!=NULL);
strResult =pCookie->strResult;
return true;
}