📄 _pi3expr.cpp
字号:
: eType( STRING ), pString( pTheString ) { assert( pString ); };
FunctionArgument( int iTheNumber )
: eType( NUMBER ), iNumber( iTheNumber ) {};
FunctionArgument( _Pi3Expression *pTheExpr )
: eType( EXPRESSION ), pExpr( pTheExpr ) { assert( pExpr ); };
~FunctionArgument()
{
switch( eType )
{
case STRING:
PI_DELETE( pString ); break;
case NUMBER:
break;
case EXPRESSION:
PI_DELETE( pExpr ); break;
default:
assert( 0 );
};
};
int Write( Context &tContext, char *pszBuffer, int iLength ) const
{
switch( eType )
{
case STRING: {
int iValueLen = pString->Len();
int iLen = iValueLen>iLength ? iLength : iValueLen;
if ( iLen>0 && pszBuffer )
{ strncpy( pszBuffer, *pString, iLen ); };
return iValueLen;
};
case NUMBER: {
enum { NUM_BUF=63 };
char szBuf[NUM_BUF+1];
sprintf( szBuf, "%d", iNumber );
int iValueLen = strlen( szBuf );
int iLen = iValueLen>iLength ? iLength : iValueLen;
strncpy( pszBuffer, szBuf, iLen );
return iValueLen;
};
case EXPRESSION:
return Internal_ExpressionToString(
tContext, pExpr, pszBuffer, iLength );
default:
assert( 0 );
};
assert( 0 );
return -1;
};
void WriteDebugTree( int iIndent ) const
{
switch( eType )
{
case STRING:
cerr << "STRING:<" << *pString << ">";
break;
case NUMBER:
cerr << "NUMBER:<" << iNumber << ">" << endl;
break;
case EXPRESSION:
cerr << endl;
pExpr->WriteDebugTree( iIndent+1 );
break;
default:
assert( 0 );
};
};
};
int iOK;
/* --- some useful methods --- */
void ExpressionToNumber( Context &tContext,
_Pi3Expression *pExpr, int &iResult ) const
{
enum { BUF_SIZE=63 };
char szBuf[BUF_SIZE+1];
szBuf[BUF_SIZE]='\0';
register int iNumberLength =
pExpr->Write( tContext, szBuf, BUF_SIZE );
iResult = iNumberLength>0 ? atoi( szBuf ) : iNumberLength;
};
void FunctionArgumentToNumber( Context &tContext,
FunctionArgument *pArg, int &iResult ) const
{
if ( pArg->eType==FunctionArgument::NUMBER )
{
iResult = pArg->iNumber;
}
else
{
enum { BUF_SIZE=63 };
char szBuf[BUF_SIZE+1];
*szBuf='\0';
int iNumberLength = pArg->Write( tContext, szBuf, BUF_SIZE );
assert( iNumberLength!=-1 );
iResult = iNumberLength>0 ? atoi( szBuf ) : iNumberLength;
};
};
int FunctionArgumentToString( Context &tContext,
FunctionArgument *pArg, char *pszBuffer, int iLength ) const
{
return pArg->Write( tContext, pszBuffer, iLength );
};
FunctionArgument *ExpressionToFunctionArgument( _Pi3Expression *pExpr )
{
if ( !pExpr )
{ return 0; };
if ( !pExpr->IsStatic() )
{ return PI_NEW( FunctionArgument( pExpr ) ); };
/* --- dummy --- */
PIHTTP tPIHTTP( (PIDB *)0 );
Context tContext( 0, tPIHTTP, 0 );
int iLen = pExpr->Write( tContext, 0, 0 );
if ( iLen==-1 )
{
assert( 0 );
PI_DELETE( pExpr );
return 0;
};
if ( !iLen )
{
PI_DELETE( pExpr );
return PI_NEW( FunctionArgument( PI_NEW( PIString ) ) );
}
char *pBuffer = PI_NEW( char[iLen+1] );
assert( pBuffer );
iLen = pExpr->Write( tContext, pBuffer, iLen );
/* --- done with expression --- */
PI_DELETE( pExpr );
FunctionArgument *pArg = PI_NEW( FunctionArgument(
PI_NEW( PIString( pBuffer, iLen ) ) ) );
PI_DELETE( [] pBuffer );
return pArg;
};
public:
FunctionComponent()
: iOK( 0 )
{};
virtual ~FunctionComponent()
{};
virtual int IsOK() const { return iOK; };
/* --- pure virtual functions for derived classes --- */
virtual const char *GetName() const=0;
virtual int Min()=0;
virtual int Max()=0;
/* ---
Optimize expression. Return 1 on success, 0 on error
--- */
virtual int Compile( DblList &lExpressions, PIString &sError )=0;
/* --- public functions --- */
static FunctionComponent *MakeFunctionComponent( PIString &sFunctionName,
TokenSource &tSource, FnPi3Write *pFunctions,
PIString &sError, int &iNestedMessage );
};
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class TruncFunctionComponent : public FunctionComponent
{
private:
FunctionArgument *pString;
FunctionArgument *pLength;
public:
TruncFunctionComponent()
: FunctionComponent(),
pString( 0 ),
pLength( 0 )
{};
virtual ~TruncFunctionComponent()
{
PI_DELETE( pString );
PI_DELETE( pLength );
};
virtual const char *GetName() const { return "trunc"; };
/* --- */
virtual void WriteDebugTree( int iIndent ) const
{
for(int i=0; i<iIndent; i++ )
{ cerr << INDENT_PATTERN; };
cerr << "Function:'" << GetName() << "'";
if ( IsStatic() )
{ cerr << "<Static>"; }
else
{ cerr << "<Dynamic>"; }
if ( !pString )
{ cerr << endl; return; };
pString->WriteDebugTree( iIndent );
assert( pLength );
cerr << ", ";
pLength->WriteDebugTree( iIndent );
};
/* --- */
virtual int Write( Context &tContext, char *pszBuffer, int iLength ) const
{
if ( !pString )
{ return 0; }; /* --- string is empty --- */
assert( pLength );
int iTruncLength;
if ( pLength->eType==FunctionArgument::NUMBER )
{ iTruncLength = pLength->iNumber; }
else
{
assert( pLength->eType==FunctionArgument::EXPRESSION );
ExpressionToNumber( tContext, pLength->pExpr, iTruncLength );
};
if ( iTruncLength<=0 )
{
if ( !iTruncLength )
{ return 0; };
/* else iTruncLength==-1 */
assert( 0 );
const char pError[] = "_Pi3Expression::trunc(): invalid length";
strncpy( pszBuffer, pError, iLength );
return ((int)sizeof( pError ));
};
/* ---
Write String
--- */
if ( pString->eType==FunctionArgument::EXPRESSION )
{
int iRet = pString->pExpr->Write( tContext, pszBuffer,
iTruncLength );
if ( iRet==-1 )
{
assert( 0 );
return -1;
};
if ( iRet<iTruncLength )
{ return iRet; };
return iTruncLength;
}
else
{
assert( pString->eType==FunctionArgument::STRING );
PIString &sString = *( pString->pString );
assert( sString.Len() );
if ( sString.Len()<iTruncLength )
{ iTruncLength = sString.Len(); };
strncpy( pszBuffer, sString, iTruncLength );
return iTruncLength;
};
};
virtual int Min() { return 2; };
virtual int Max() { return 2; };
/* ---
Optimize expression. Return 1 on success, 0 on error
--- */
virtual int Compile( DblList &lExpressions, PIString &sError )
{
DblListIterator i( lExpressions );
if ( i.BadIndex() ) { return 0; };
_Pi3Expression *pEString = (_Pi3Expression *)i.Current();
i++;
if ( i.BadIndex() ) { return 0; };
_Pi3Expression *pELength = (_Pi3Expression *)i.Current();
/* --- make dummy PIHTTP object --- */
PIHTTP tPIHTTP( (PIDB *)0 );
Context tContext( 0, tPIHTTP, 0 );
/* --- clear the list --- */
assert( lExpressions.Size()==Min() );
assert( lExpressions.Size()==Max() );
lExpressions.Clear();
/* --- set string argument --- */
if ( !pEString->IsStatic() )
{
pString = PI_NEW( FunctionArgument( pEString ) );
}
else
{
int iLength = pEString->Write( tContext, 0, 0 );
if ( iLength<0 )
{
assert( 0 );
return -1;
};
if ( iLength==0 )
{
PI_DELETE( pEString );
pEString = 0;
}
else
{
char *pBuffer = PI_NEW( char[iLength+1] );
pEString->Write( tContext, pBuffer, 0 );
pBuffer[iLength] = '\0';
pString = PI_NEW( FunctionArgument(
PI_NEW( PIString( pBuffer, iLength ) ) ) );
PI_DELETE( [] pBuffer );
};
};
/* --- set length argument, if string is non-empty --- */
if ( pString )
{
if ( !pELength->IsStatic() )
{
pLength = PI_NEW( FunctionArgument( pELength ) );
}
else
{
/* --- preprocess expression to a number --- */
int iNumber=-1;
ExpressionToNumber( tContext, pELength, iNumber );
PI_DELETE( pELength );
if ( iNumber==-1 )
{
sError = "_Pi3Expression::trunc(): invalid length argument";
return 0;
};
pLength = PI_NEW( FunctionArgument( iNumber ) );
};
};
/* --- done --- */
iOK = 1;
return 1;
};
virtual int IsStatic() const
{
if ( !pString )
{ return 1; }; /* --- static because its empty --- */
assert( pLength );
return pString->eType==FunctionArgument::STRING &&
pLength->eType==FunctionArgument::NUMBER;
};
};
/*____________________________________________________________________________*\
*
Class:
Description:
This function should be re-written.
\*____________________________________________________________________________*/
class AlignFunctionComponent : public FunctionComponent
{
private:
FunctionArgument *pString;
FunctionArgument *pLength;
FunctionArgument *pFlags;
FunctionArgument *pPadding;
public:
AlignFunctionComponent()
: FunctionComponent(),
pString( 0 ),
pLength( 0 ),
pFlags( 0 ),
pPadding( 0 )
{};
virtual ~AlignFunctionComponent()
{
PI_DELETE( pString );
PI_DELETE( pLength );
PI_DELETE( pFlags );
PI_DELETE( pPadding );
};
virtual const char *GetName() const { return "align"; };
/* --- */
virtual void WriteDebugTree( int iIndent ) const
{
for(int i=0; i<iIndent; i++ )
{ cerr << INDENT_PATTERN; };
cerr << "Function:'" << GetName() << "'";
if ( IsStatic() )
{ cerr << "<Static>"; }
else
{ cerr << "<Dynamic>"; }
assert( pString );
pString->WriteDebugTree( iIndent );
cerr << ", ";
assert( pFlags );
pFlags->WriteDebugTree( iIndent );
cerr << ", ";
assert( pPadding );
pPadding->WriteDebugTree( iIndent );
};
/* --- */
virtual int Write( Context &tContext, char *pszBuffer, int iLength ) const
{
assert( pString );
assert( pLength );
assert( pFlags );
assert( pPadding );
assert( pszBuffer || !iLength );
/* --- get field length --- */
int iFieldLength; /* the length of the field to write */
FunctionArgumentToNumber( tContext, pLength, iFieldLength );
/* --- give error if field length is wrong --- */
if ( iFieldLength<=0 )
{
if ( !iFieldLength )
{
return 0;
};
/* else iFieldLength==-1 */
const char pError[] = "_Pi3Expression::align(): invalid length";
if ( iLength>0 )
{ strncpy( pszBuffer, pError, iLength ); };
return ((int)sizeof( pError ));
};
enum { BUF_SIZE=127 };
/* --- get padding --- */
char szPaddingBuf[BUF_SIZE+1];
int iPaddingLen = pPadding->Write( tContext, szPaddingBuf,
BUF_SIZE );
if ( iPaddingLen==-1 )
{ return -1; };
if ( iPaddingLen>BUF_SIZE )
{ iPaddingLen=BUF_SIZE; };
PIString sPadding;
if ( iPaddingLen>0 )
{
szPaddingBuf[iPaddingLen]='\0';
sPadding = szPaddingBuf;
}
else
{
sPadding = " ";
iPaddingLen = sPadding.Len();
};
/* --- get flags --- */
char szFlagsBuf[BUF_SIZE+1];
int iFlagsLen = pFlags->Write( tContext, szFlagsBuf, BUF_SIZE );
if ( iFlagsLen==-1 )
{ return -1; };
if ( iFlagsLen>BUF_SIZE )
{ iFlagsLen = BUF_SIZE; };
char *pszFlagsBuf = szFlagsBuf;
/* --- eat leading whitespace --- */
while( iFlagsLen>0 && (isspace(*pszFlagsBuf)) )
{
iFlagsLen--;
pszFlagsBuf++;
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -