CStageManager class

Pipelines v2.0

 

Member variables, Member functions

Home

 

Description

 

The CStageManager() class provides access to a range of stage resources, including; parsing, extracting and validating your stage command argument, issuing error and warning messages on behalf of your stage, reading and writing input and output stream records, testing stream connectivity and other general purpose support functions. The StageManager is at the core of Pipelines and it serves as a central class which provides an interface to essential stage services that allow you to control how your stage operates in a multi-stream pipeline configuration.

 

Definition

 

The following class definition is an edited version; it details only those members which are accessible and of use to you. In addition; any examples that may be shown are only intended as a demonstration of how certain functions might be used, they do not represent best practice nor do they take into account the scope and de-allocation of class objects.

 

// Definitions for interface to stage DLLs.
typedef DWORD ( *BEGIN_STAGE )( CStageInitInfo *a_pManager );
#define BEGIN_STAGE_FCN "BeginStage"
 
class CStageManager 
{
    public:
 
    // Pipeline, Stage and Stream functions.
    CStage *GetStage( CProcess &a_Process );
    bool ReadRecord( CProcess &a_Process, DWORD a_dwInStream, CString *a_pBuffer );
    bool ReadAnyRecord( CProcess &a_Process, CString *a_pBuffer );
    bool PeekRecord( CProcess &a_Process, DWORD a_dwInStream, CString *a_pBuffer );
    int PeekAnyRecord( CProcess &a_Process, CString *a_pBuffer );
    bool WriteRecord( CProcess &a_Process, DWORD a_dwOutStream, CString *a_pszRecord );
    bool ConsumeRecord( CProcess &a_Process, DWORD a_dwInStream );
    void StageMessage( CProcess &a_Process, DWORD a_dwType, const char *a_pMessage, ... );
    bool StageMessage( CProcess &a_Process, DWORD a_dwMsgNumber, DWORD a_dwType, ... );
    bool RuntimeError( void ) const;
    double GetProcId( void ) const;
    bool PreProcess( CProcess &a_pProcess, const char **a_pszArgument );
    void SeverOutStream( CProcess &a_Process, DWORD a_dwStream );
    void SeverInStream( CProcess &a_Process, DWORD a_dwStream );
 
    // Parsing functions.
    bool ParseForToken( CToken *a_pToken );
    bool ParseForIntegerString( CIntegerString *a_pIntString );
    bool ParseForDoubleString( CDoubleString *a_pDblString );
    bool ParseForCharacterString( CCharacterString *a_pCharString );
    bool ParseForRegExp( CProcess &a_Process, CRegExpression *a_pRegExp,
                         bool a_bCaseSensitive = true );
    bool ParseForIntegerRange( CIntegerRange *a_pIntRange );
    bool ParseForCharacter( CCharacterString *a_pCharString );
    bool ParseForCharacterRange( CCharacterRange *a_pCharRange );
 
    // Conversion functions.
    bool ConvertToInteger( CIntegerString *a_pIntString );
    bool ConvertToDouble( CDoubleString *a_pDblString );
    
    // Runtime extraction functions.
    void ExtractColumnRange( CExtractRange *a_pRange );
    void ExtractWordRange( CExtractRange *a_pRange );
    void ExtractFieldRange( CExtractRange *a_pRange );
 
    bool RegExpMatch( CRegExpression *a_pRegExp, CString &a_szSource );
    bool PatternMatch( const char *a_pszPattern, const char *a_pszSource ); 
 
    // Set the status of a stage once initialisation is complete.
    bool SetStatus( CStageInitInfo *a_pInfo );
 

    // ooRexx interface functions.

    RexxExitContext *GetRexxExitContext( void );

    RexxDirectoryObject GetRexxDirectoryObject( void );

    DWORD GetRexxVariable( const char *a_pszName, CString *a_pszValue );

    bool GetRexxStem( const char *a_pszName, std::list< CString > *a_plStem );

    bool GetRexxArray(const char *a_pszName, std::list< CString > *a_plArray );

    DWORD GetRexxStemEntry( const char *a_pszName, CString *a_pszValue, DWORD a_dwIndex );

    DWORD GetRexxArrayEntry( const char *a_pszName, CString *a_pszValue, DWORD a_dwIndex );

    DWORD GetRexxStemSize( const char *a_pszName );

    DWORD GetRexxArraySize( const char *a_pszName );

    bool IsRexxVariable(const char *a_pszName, DWORD a_dwType );

    bool IsRexxStem( const char *a_pszName );

    bool IsRexxArray( const char *a_pszName );

    CRexxEntry *AddRexxEntry( void );
};
 

Member variables

 
None.
 

Member functions

 

 
CStage *CStageManager::GetStage(
    _in                          CProcess &a_Process );
 

 

    

Purpose

Use GetStage() to get a pointer to your CStage.

 

With this pointer; you can access your stage arguments, determine your position in the pipeline, set and test your input and output stream connections and more.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

    

Returns

 

 

CStage *

A pointer to your CStage class object.

 

    

Messages

None

 

    

Usage

To get a pointer to your CStage object:

 

DWORD CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::ReadRecord(
    _in                         CProcess &a_Process,
    _in                         DWORD a_dwInStream,
    _inout                      CString *a_pszRecord );
 

 

    

Purpose

Use ReadRecord() to read a record from the specified input stream a_dwInStream.

 

ReadRecord() issues a read request against the specified input stream a_dwInStream. The function waits for a record to become available; effectively suspending your stage until the read can be satisfied. The length of time that your stage remains suspended cannot be determined. Once a record has become available; the function stores that record in the CString buffer a_pszRecord, removes the record from the input stream (releasing the stage connected to the write-end of the stream, from its suspended state) and returns control to your stage.

 

A stage which calls ReadRecord(); delays the records.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

DWORD a_dwInStream

[in] The number of the input stream to read from.

 

CString *a_pszRecord

[in,out] The address of a buffer in which to store the input record.

 

    

Returns

 

 

bool

true if the read request was successful, otherwise; false which indicates that the input stream is at end-of-file.

 

    

Messages

None

 

    

Usage

To read a record from your primary input stream:

 

DWORD CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
 
    // Record buffer.
    CString szRecord;
 
    while( true )
    {
        // Read a record from my primary input stream.
        if( !pManager->ReadRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary input stream.
            break;
        }
 
        //
        // TODO: operate on the record here.
        //
 
        ...
 
        // Write the record to my primary output stream.
        if( !pManager->WriteRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary output stream.
            break;
        }
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::ReadAnyRecord(
    _in                            CProcess &a_Process,
    _inout                         CString *a_pszRecord );
 

 

    

Purpose

Use ReadAnyRecord() to read a record from any connected input stream.

 

ReadAnyRecord() issues a read request against all your input streams. The function waits for a record to become available on any input stream; effectively suspending your stage until the read can be satisfied. The length of time that your stage remains suspended cannot be determined. Once a record has become available; the function stores that record in the CString buffer a_pszRecord, removes the record from the input stream (releasing the stage connected to the write-end of the stream, from its suspended state) and returns control to your stage.

 

A stage which calls ReadAnyRecord(); delays the records.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

CString *a_pszRecord

[in,out] The address of a buffer in which to store the input record.

 

    

Returns

 

 

bool

true if the read request was successful, otherwise; false which indicates that all input streams are at end-of-file.

 

    

Messages

None

 

    

Usage

To read a record from any of your input streams:

 

DWORD CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
 
    // Record buffer.
    CString szRecord;
 
    while( true )
    {
        // Read a record from any of my input streams.
        int nStream = pManager->ReadAnyRecord( *this, &szRecord );
 
        // Test for end-of-file.
        if( nStream < 0 )
        {
            // This is the end-of-file on all my input streams.
            break;
        }
 
        //
        // TODO: operate on the record here.
        //
 
        ...
 
        // Write the record to my primary output stream.
        if( !pManager->WriteRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary output stream.
            break;
        }
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::PeekRecord(
    _in                         CProcess &a_Process,
    _in                         DWORD a_dwInStream,
    _inout                      CString *a_pszRecord );
 

 

    

Purpose

Use PeekRecord() to peek at a record on the specified input stream a_dwInStream.

 

PeekRecord() issues a read request against the specified input stream a_dwInStream. The function waits for a record to become available; effectively suspending your stage until the read can be satisfied. The length of time that your stage remains suspended cannot be determined. Once a record has become available; the function stores that record in the CString buffer a_pszRecord, but does not remove the record from the input stream (leaving the stage connected to the write-end of the stream, in its suspended state) and returns control to your stage.

 

A stage which calls PeekRecord(), then WriteRecord(), then ConsumeRecord(), in that order; does not delay the records.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

DWORD a_dwInStream

[in] The number of the input stream to read from.

 

CString *a_pszRecord

[in,out] The address of a buffer in which to store the input record.

 

    

Returns

 

 

bool

true if the read request was successful, otherwise; false which indicates that the input stream is at end-of-file.

 

    

Messages

None

 

    

Usage

To peek at a record on your primary input stream:

 

CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
 
    // Record buffer.
    CString szRecord;
 
    while( true )
    {
        // Peek at a record on my primary input stream.
        if( !pManager->PeekRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary input stream.
            break;
        }
 
        //
        // TODO: operate on the record here.
        //
 
        ...
 
        // Write the record to my primary output stream.
        if( !pManager->WriteRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary output stream.
            break;
        }
 
        // Release the stage that I read from.
        pManager->ConsumeRecord( *this, 0 );
    }
 
    return( _RC_SUCCESS_ );
}

 

 
int CStageManager::PeekAnyRecord(
    _in                           CProcess &a_Process,
    _inout                        CString *a_pszRecord );
 

 

    

Purpose

Use PeekAnyRecord() to peek at a record on any connected input stream.

 

PeekAnyRecord() issues a read request against all your input streams. The function waits for a record to become available on any input stream; effectively suspending your stage until the read can be satisfied. The length of time that your stage remains suspended cannot be determined. Once a record has become available; the function stores that record in the CString buffer a_pszRecord, but does not remove the record from the input stream (leaving the stage connected to the write-end of the stream, in its suspended state) and returns control to your stage.

 

A stage which calls PeekAnyRecord(), then WriteRecord(), then ConsumeRecord(), in that order; does not delay the records.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

CString *a_pszRecord

[in,out] The address of a buffer in which to store the input record.

 

    

Returns

 

 

int

The zero-based index number of the stream which satisfied the read request, otherwise; a value less than zero, which indicates that all input streams are at end-of-file.

 

    

Messages

None

 

    

Usage

To peek at a record from any of your input streams:

 

CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
 
    // Record buffer.
    CString szRecord;
 
    while( true )
    {
        // Peek at a record on any of my input streams.
        int nStream = pManager->PeekAnyRecord( *this, &szRecord );
        
        // Test for end-of-file.
        if( nStream < 0 )
        {
            // This is the end-of-file on all my input streams.
            break;
        }
 
        //
        // TODO: operate on the record here.
        //
 
        ...
 
        // Write the record to my primary output stream.
        if( !pManager->WriteRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary output stream.
            break;
        }
 
        // Release the stage that I read from.
        pManager->ConsumeRecord( *this, nStream );
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::WriteRecord(
    _in                          CProcess &a_Process,
    _in                          DWORD a_dwOutStream,
    _in                          CString *a_pszRecord );
 

 

    

Purpose

Use WriteRecord() to write a record to the specified output stream a_dwOutStream.

 

WriteRecord() writes the record from the CString buffer a_pszRecord to the specified output stream a_dwOutStream. The function suspends your stage until the target stage connected to output stream a_dwOutStream has consumed the record. That is to say; your stage remains suspended pending service by the StageManager until it is released by a call on the read-end of the stream, through any of the functions; ReadRecord(), ReadAnyRecord() or ConsumeRecord(). The length of time that your stage remains suspended cannot be determined. Once the record has been consumed; the function releases your stage from its suspended state and returns control to your stage.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

DWORD a_dwOutStream

[in] The number of the output stream to write to.

 

CString *a_pszRecord

[in] The address of a buffer which contains the output record.

 

    

Returns

 

 

bool

true if the write request was successful, otherwise; false which indicates that the output stream is at end-of-file.

 

    

Messages

None

 

    

Usage

To write a record to your primary output stream:

 

CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
 
    // Record buffer.
    CString szRecord;
 
    while( true )
    {
        // Read a record from my primary input stream.
        if( !pManager->ReadRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary input stream.
            break;
        }
 
        //
        // TODO: operate on the record here.
        //
 
        ...
 
        // Write the record to my primary output stream.
        if( !pManager->WriteRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary output stream.
            break;
        }
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::ConsumeRecord(
    _in                            CProcess &a_Process,
    _in                            DWORD a_dwInStream );
 

 

    

Purpose

Use ConsumeRecord() to remove a record from the specified input stream a_dwInStream.

 

ConsumeRecord() removes a record from the specified input stream a_dwInStream (releasing the stage connected to the write-end of the stream, from its suspended state) and returns control to your stage. There must be a record in the input stream for ConsumeRecord() to remove; you must first have made a call to either the PeekRecord() or PeekAnyRecord() function before making a call to ConsumeRecord(). Both peek functions issue a read record request but they do not automatically consume the record once the read is complete (leaving the stage connected to the write-end of the stream, in its suspended state). ConsumeRecord() allows you to remove an input stream record as and when you require.

 

A stage which calls PeekRecord() or PeekAnyRecord(), then WriteRecord(), then ConsumeRecord(), in that order; does not delay the records.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

DWORD a_dwInStream

[in] The number of the input stream to consume a record from.

 

    

Returns

 

 

bool

true if the consume was successful, otherwise; false which indicates that the input stream is at end-of-file.

 

    

Messages

None

 

    

Usage

To create a stage which does not delay the records; use the following construct:

 

CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
 
    // Record buffer.
    CString szRecord;
 
    while( true )
    {
        // Peek at a record on my primary input stream.
        if( !pManager->PeekRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary input stream.
            break;
        }
 
        //
        // TODO: operate on the record here.
        //
 
        ...
 
        // Write the record to my primary output stream.
        if( !pManager->WriteRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary output stream.
            break;
        }
 
        // Release the stage that I read from.
        pManager->ConsumeRecord( *this, 0 );
    }
 
    return( _RC_SUCCESS_ );
}

 

 
void CStageManager::StageMessage(
    _in                           CProcess &a_Process,
    _in                           DWORD a_dwType,
    _in_opt                       const char *a_pMessage,
    _in_opt                       ... );
 

 

    

Purpose

Use StageMessage() to write a synchronised stage message to the console.

 

In a multi-stage, multi-pipeline configuration; at any one time there may be more than one stage writing messages to the console at the same time, and their output must be managed in order to prevent output overlap. CApplMessage() provides this mechanism, by locking the console for output; it ensures that messages from multiple output sources are written uninterrupted and in the correct sequence. You should use this version of StageMessage() when you want to write a free-form message to the console.

 

There are two flavours of StageMessage(); this version, and the canned message version; which follows, and both allow you to write a warning or error message to the console.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

DWORD a_dwType

[in] The type of message to issue; this can be a warning message or error message.

 

The following values define the type of message to issue:

 

#define _WARNING_    1

#define _ERROR_      2

 

const char *a_pMessage

[in,opt] A constant character pointer to the message to display.

 

. . .

[in,opt] The function arguments.

 

    

Returns

 

void

 

    

Messages

None

 

    

Usage

To issue a free-form message; simply specify the message as an operand on the StageMessage function:

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    pStage->MinInStreamsRequired( 1 );
    pStage->MaxInStreamsAllowed( 2 );
    pStage->MinOutStreamsRequired( 1 );
    pStage->MaxOutStreamsAllowed( 1 );
 
    // Point to my command argument.
    const char *pszArgument = pStage->Argument();
 
    // My stage allows up to two input streams to be connected, however, if there
    // is only one input stream connected; then warn the user.
 
    CInStream *pInStream = pStage->GetInStream( 1 );
    if( pInStream && pInStream->IsDisConnected() )
    {
        // My secondary input stream is not connected!
        pManager->StageMessage( *this, _WARNING_, “There is only one input stream connected!” );
        ...
    }
 
    ...
 
    return( true );
}

 

 
bool CStageManager::StageMessage(
    _in                           CProcess &a_Process,
    _in                           DWORD a_dwMsgNumber,
    _in                           DWORD a_dwType,
    _in_opt                       ... );
 

 

    

Purpose

Use StageMessage() to write a synchronised stage message to the console.

 

In a multi-stage, multi-pipeline configuration; at any one time there may be more than one stage writing messages to the console at the same time, and their output must be managed in order to prevent output overlap. CApplMessage() provides this mechanism, by locking the console for output; it ensures that messages from multiple output sources are written uninterrupted and in the correct sequence. You should use this version of StageMessage() when you want to write a canned message to the console.

 

There are two flavours of StageMessage(); this version, and the free-form message version; which precedes, and both allow you to write a warning or error message to the console.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

DWORD a_dwMsgNumber

[in]  The canned stage message number of the message template that you want to issue.

 

DWORD a_dwType

[in] The type of message to issue; this can be a warning message or error message.

 

The following values define the type of message to issue:

 

#define _WARNING_    1

#define _ERROR_      2

 

. . .

[in,opt] The function arguments.

 

    

Returns

 

 

bool

true if the message index is in the range, otherwise; false which indicates that the message index is not in the range.

 

    

Messages

None

 

    

Usage

To issue a specific canned stage message; simply specify the canned message number as an operand on the StageMessage function:

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    pStage->MinInStreamsRequired( 1 );
    pStage->MaxInStreamsAllowed( 2 );
    pStage->MinOutStreamsRequired( 1 );
    pStage->MaxOutStreamsAllowed( 1 );
 
    // Point to my command argument.
    const char *pszArgument = pStage->Argument();
 
    // My stage does not require a command argument; if there is one,
    // then it is unexpected.
 
    if( *pszArgument )
    {
        // Tell the user the type of argument that I expect; issue canned
        // stage message number 33.
        pManager->StageMessage( *this, 33, _ERROR_, pszArgument );
        return( false );
    }
 
    return( true );
}

 

 
bool CStageManager::RuntimeError( void ) const;
 

 

    

Purpose

Use RuntimeError() to determine if the StageManager has issued a runtime quiesce command.

 

When any of the stage’s in a pipeline report a runtime error (by returning a value of _RC_FAIL_ from their required stage DLL interface function Go() ) the StageManager begins terminating the pipeline by first setting the runtime quiesce flag, which indicates that the pipeline is quiescent. Next the StageManager disconnects the input and output stream connections for your stage; which will cause the next input read or output write request to fail, allowing your stage to terminate, as if at end-of-file. However, Pipelines is not pre-emptive; the StageManager must first wait for all active stages in the pipeline to request one of its stream services in order to detect that the pipeline is terminating. Your stage may not request i/o on a regular basis; it may for example, sort its input records, which may consist of millions or more entries; where your stage may be pre-occupied for a considerable amount of time and will not be reading or writing any input or output records. The RuntimeError() function allows you to check if the quiesce command has been issued by the StageManager, as an when you need to; so that your stage does not cause the pipeline to ‘seemingly’ hang while your stage needlessly continues with its runtime phase; in a pipeline that is waiting to terminate.

 

    

Parameters

 

 

void

 

    

Returns

 

 

bool

true if the StageManager has issued a runtime quiesce, otherwise; false which indicates that your stage can safely continue with its runtime phase.

 

    

Messages

None

 

    

Usage

The following example shows an edited excerpt from the CSort stage commands’ multiple-key-field recursive sort mechanism. The RuntimeError() function ensures that the RecurseCompare() function un-winds once a runtime error has occurred:

 

bool CSort::RecurseCompare( const CString *l,
                            const CString *r,
                            std::vector< m_Position >::iterator iPos )
{
    // Check if the pipeline is quiescing.
    if( m_pManager->RuntimeError() )
        return( false );
 
    // iPos points to the current sort range.
    // So, extract/isolate the portion defined by iPos and validate the comparison.
 
    m_Position *pPos = &( *iPos );
 
    DWORD dwFrom = pPos->m_dwFrom - 1;
    DWORD dwFor = pPos->m_dwTo - dwFrom;
 
    CString szlMid = l->Mid( dwFrom, dwFor );
    CString szrMid = r->Mid( dwFrom, dwFor );
 
    ...
 
    // The comparison moves down to the next level.
    if( szlMid == szrMid )
    {
        if( ( iPos + 1 ) != m_vPosition.end() )
            return( RecurseCompare( l, r, iPos + 1 ) );
    }
 
    if( pPos->m_bAscending )
        return( szlMid < szrMid ); 
 
    return( szlMid > szrMid ); 
}

 

 
double CStageManager::GetProcId( void ) const;
 

 

    

Purpose

Use GetProcId() to get the Process Identification number of the StageManager.

 

Many of the builtin stages’ that are provided with Pipelines use this number when creating uniquely identifiable names for a range of objects, including; events, mutexes and work files. By using the Process Identification number of the StageManager as part of a name for a global resource, it may help when debugging your new stage. As multiple instances of Pipelines may execute concurrently (and that might mean multiple instances of identical pipelines, with multiple instances of your new stage); creating events, mutexes and work filenames with this number in combination with your pipeline and stage number can make identifying which resource belongs to which pipeline and stage, a great deal easier.

 

    

Parameters

 

void

 

    

Returns

 

 

double

The Process Identification number of the StageManager which loaded and dispatched your stage.

 

    

Messages

None

 

    

Usage

To create a work filename which uniquely identifies your stage as the owner; you might use the following approach:

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // Create a unique filename.
    CString szTmpFile;
    szTmpFile.Format( "TEMP-%.5d%.3d%.3d.txt", ( DWORD )pManager->GetProcId(), Pipeline(), Stage() );
 
    ...
 
    return( true );
}

 

 
bool CStageManager::PreProcess(
    _in                         CProcess &a_Process,
    _inout                      const char **a_pszArgument );
 

 

    

Purpose

Use PreProcess() to extract the stage command arguments specified in the CASEI() and ZONE() pre-process functions.

 

There are a number of builtin Pipelines stage’s which operate as simple selection filters; writing records to their primary and secondary output streams, depending on the content of an input record. Consider the FROMLABEL stage for example. By default, all of these filter type stage’s check for the existence/or not of the specified text starting in the first column of an input record. However, the PreProcess() function extends this basic selection capability; instructing the manager to extract a substring of the record, determined by the column, word or field range, and optionally; to translate both the stage operands and the content of the input records to uppercase, and present this altered record to the stage when a read-record is requested. The function does not alter the way in which a stage processes its input and output records, it only alters the format of the record which is presented to the stage. When the stage performs a subsequent write-record request, the manager writes the original unmodified input record to the specified output stream.

 

PreProcess() ensures that the stage command argument syntax for a position or range on which to operate is identical for all filter type stages.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

const char **a_pszArgument

[in,out] The address of a pointer to your stage command argument.

 

    

Returns

 

 

bool

true if the stage command argument is properly formed, otherwise; false which indicates a stage command parsing error.

 

    

Messages

None

 

    

Usage

To enable CASEI() or ZONE() pre-processing:

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // Point to my command argument.
    const char *pszArgument = pStage->Argument();
 
    // Perform any preprocessing required.
    if( !pManager->PreProcess( *this, &pszArgument ) )
        return( false );
 
    // My stage requires a delimted string.
 
    CString szString;
    CCharacterString *pCharString = new CCharacterString( *this );
 
    pCharString->m_bRequired = true;
    pCharString->m_pszSource = &pszArgument;
    pCharString->m_pszTarget = &szString;
 
    // Extract the string.
    if( !pManager->ParseForCharacterString( pCharString ) )
        return( false );
 
    ...
 
    return( true );
}

 

Excerpt

 

The following example shows how the ZONE() pre-process function greatly extends the selection capability of mystage. By using the PreProcess() function; mystage is able to restrict the selection of records to those that contain the phrase text to find in the third-from-last (+) delimited word of each input record.

 

pipe < myfile.txt
    ...
    | mystage zone( ws ‘+’ w-3 ) /text to find/
    | > textfound.txt

 

 
void CStageManager::SeverOutStream(
    _in                             CProcess &a_Process,
    _in                             DWORD a_dwOutStream );
 

 

    

Purpose

Use SeverOutStream() to disconnect the specified output stream a_dwOutStream.

 

SeverOutStream() disconnects both the specified output stream a_dwOutStream and the corresponding input stream of the stage connected to the read-end of the stream. If it is suspended; the stage connected to the read-end of the stream is released from its suspended state and the stage regains control immediately. Any subsequent read request made on the read-end of the stream will return an end-of-file condition.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

DWORD a_dwOutStream

[in] The number of the output stream to sever.

 

    

Returns

 

void

 

    

Messages

None

 

    

Usage

To disconnect an output stream:

 

DWORD CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // My stage writes only the first 100 input stream records to its
    // primary output stream. The stage then disconnects its primary 
    // output stream and begins writing input stream records to its
    // secondary output stream.
 
    // The target output stream is initially the primary output stream. 
    DWORD dwOutStream = 0;
 
    // Record buffer.
    CString szRecord;
 
    // Accumulate the number of input records read. 
    DWORD dwRecCount = 0;
 
    while( true )
    {
        // Read a record from my primary input stream.
        if( !pManager->ReadRecord( *this, 0, &szRecord ) ) 
        {
            // This is the end-of-file on my primary input stream.
            break;
        }
 
        if( dwRecCount == 100 )
        {
            pManager->SeverOutStream( 0 );
            // Switch to my secondary output stream.
            dwOutStream = 1;
        }
 
        // Write the record to the specified output stream.
        if( !pManager->WriteRecord( *this, dwOutStream, &szRecord ) )
        {
            // This is the end-of-file on this output stream.
            break;
        }
 
        ++dwRecCount;
    }
 
    return( _RC_SUCCESS_ );
}

 

 
void CStageManager::SeverInStream(
    _in                            CProcess &a_Process,
    _in                            DWORD a_dwInStream );
 

 

    

Purpose

Use SeverInStream() to disconnect the specified input stream a_dwInStream.

 

SeverInStream() disconnects both the specified input stream a_dwInStream and the corresponding output stream of the stage connected to the write-end of the stream. If it is suspended; the stage connected to the write-end of the stream is released from its suspended state and the stage regains control immediately. Any subsequent write request made on the write-end of the stream will return an end-of-file condition.

 

Where you place the SeverInStream() function in your stage is extremely important; it can have a significant effect on how a pipeline behaves. Your stage must be able to anticipate the effect it may have when it disconnects an input stream and forces an end-of-file to propagate backward through a multi-stream pipeline.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object)

 

DWORD a_dwInStream

[in] The number of the input stream to sever.

 

    

Returns

 

void

 

    

Messages

None

 

    

Usage

To disconnect an input stream:

 

DWORD CMyStage::Go( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // My stage reads only the first 100 input stream records from its
    // primary input stream. The stage then disconnects its primary 
    // input stream and begins reading records from its secondary input
    // stream and writes them to its primary output stream.
 
    // The source input stream is initially the primary input stream.
    DWORD dwInStream = 0;
 
    // Record buffer.
    CString szRecord;
 
    // Accumulate the number of input records read.
    DWORD dwRecCount = 0;
 
    while( true )
    {
        // Read a record from the specified input stream.
        if( !pManager->ReadRecord( *this, dwInStream, &szRecord ) )
        {
            // This is the end-of-file on this input stream.
            break;
        }
 
        if( dwRecCount == 100 )
        {
            pManager->SeverInStream( 0 );
            // Switch to my secondary input stream.
            dwInStream = 1;
        }
 
        // Write the record to my primary output stream.
        if( !pManager->WriteRecord( *this, 0, &szRecord ) )
        {
            // This is the end-of-file on my primary output stream.
            break;
        }
 
        ++dwRecCount;
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::ParseForToken(
    _inout                         CToken *a_pToken );
 

 

    

Purpose

Use ParseForToken() to extract the next token or delimited phrase from your stage command argument.

 

ParseForToken() uses the CToken class object to extract a token or delimited phrase from your stage command argument. The ParseForToken() function, which can skip leading and trailing delimiters; extracts the token or phrase and stores it at the address specified in the CToken member m_pszTarget.

 

    

Parameters

 

 

CToken *a_pToken

[in,out] A pointer to a CToken class object; which specifies the leading and trailing extraction delimiters and whether or not they can be skipped.

 

    

Returns

 

 

bool

true if the function successfully extracts a token or delimited phrase, otherwise; false which indicates an invalid or missing; required stage command argument.

 

    

Messages

None

 

    

Usage

The following example shows an edited excerpt from the CBetween stage class commands’ Initialise() function. The portion of code shown; illustrates how the ParseForToken() function is used to extract a stage command keyword.

 

bool CBetween::Initialise( void )
{

    // Access the manager.

    CStageManager *pManager = Manager();

    // Access my stage.

    CStage *pStage = pManager->GetStage( *this );

 
    ...
 
    // Access my argument.
    const char *pszArgument = pStage->Argument();
 
    CString szToken;
    CToken *pToken = new CToken( *this );
    CCharacterString *pCharacterString = new CCharacterString( *this ); 
    
    // Extract the first token and check if it is a keyword.
    pToken->m_pszSource = &pszArgument;
    pToken->m_pszTarget = &szToken;
    if( !pManager->ParseForToken( pToken ) )
    {
        pManager->StageMessage( *this, 19, _ERROR_ );
            return( false );
    }
 
    ...
 
    // Extract the 'from' string.
    pCharacterString->m_pszSource = &pszArgument;
    pCharacterString->m_pszTarget = &m_szFrom;
    pCharacterString->m_bRequired = true;
    if( m_dwFromType == m_eString )
        pCharacterString->m_bNull = true;
    else
    pCharacterString->m_bNull = false;
 
    if( !pManager->ParseForCharacterString( pCharacterString ) )
        return( false );
 
    ...
 
    // There must be more argument.
    if( !pManager->ParseForToken( m_pToken ))
    {
        pManager->StageMessage( *this, 19, _ERROR_ );
        return( false );
    }
 
    ...
 
    Return( true );
}

 

 
bool CStageManager::ParseForIntegerString(
    _inout                                 CIntegerString *a_pIntString );
 

 

    

Purpose

Use ParseForIntegerString() to extract an integer string from your stage command argument.

 

ParseForIntegerString() uses the CIntegerString class object to extract an integer string from your stage command argument. The ParseForIntegerString() function, which can skip leading and trailing delimiters, extracts and validates the format of the string and stores it at the address specified in the CIntegerString member m_pszTarget.

    

Parameters

 

 

CIntegerString *a_pIntString

[in,out] A pointer to a CIntegerString class object; which may specify a minimum and maximum allowed integer value, whether the value is a required or optional stage command argument and whether leading and trailing delimiters can be skipped or not.

 

    

Returns

 

 

bool

true if the function successfully extracts an integer string; in which case the function sets the CIntegerString member m_nReturnCode to a value of _RC_SUCCESS_.

 

Otherwise the function returns a value of false; which indicates an invalid or missing, required stage command argument. In this case the function sets the CIntegerString member m_nReturnCode to one of the following values:

 

m_nReturnCode

Meaning

 

 

_RC_NOT_FOUND_

The integer string is missing from the stage command argument.

_RC_NOT_NUMERIC_

The integer string contains non-numeric characters.

 

    

Messages

When the CIntegerString member m_bRequired is set to true and the argument is missing or invalid; ParseForIntegerString() will issue one of the following stage messages: 9, 20, 21, 60, 61.

 

    

Usage

The following example shows an edited excerpt from the CDuplicate stage class commands’ Initialise() function. The portion of code shown; illustrates how the ParseForIntegerString() function is used to extract an integer string from your stage command argument.

 

bool CDuplicate::Initialise( void )
{

    // Access the manager.

    CStageManager *pManager = Manager();

    // Access my stage.

    CStage *pStage = pManager->GetStage( *this );

 
    ...
 
    // Access my argument.
    const char *pszArgument = pStage->Argument();
 
    // Set defaults.
    m_lCopies = 1;
    
    ...
 
    if( *pszArgument )
    {
        CString szToken;
        CToken *pToken = new CToken( *this );
        CIntegerString *pIntegerString = new CIntegerString( *this ); 
 
        pIntegerString->m_pszSource = &pszArgument;
        pIntegerString->m_pszTarget = &szToken;
        pIntegerString->m_dwMinUnsignedValue = 0;
        pIntegerString->m_dwMaxUnsignedValue = _MAX_INT_ - 1;
 
        // Try to extract an integer string.
        if( pManager->ParseForIntegerString( pIntegerString ) )
        {
            pIntegerString->m_bRequired = true;
            if( !pManager->ConvertToInteger( pIntegerString ) )
               return( false );
 
            m_lCopies = pIntegerString->m_lResult;
        }
        else
        {
            ...
        }
 
        // There should be no other arguments.
        if( *pszArgument )
        {
            pManager->StageMessage( *this, 33, _ERROR_, pszArgument );
            return( false );
        }
    }
 
    ...
 
    return( true );
}

 

 
bool CStageManager::ParseForDoubleString(
    _inout                                CDoubleString *a_pDblString );
 

 

    

Purpose

Use ParseForDoubleString() to extract a double string from your stage command argument.

 

ParseForDoubleString() uses the CDoubleString class object to extract a double string from your stage command argument. The ParseForDoubleString() function, which can skip leading and trailing delimiters, extracts and validates the format of the string and stores it at the address specified in the CDoubleString member m_pszTarget.

    

Parameters

 

 

CDoubleString *a_pDblString

[in,out] A pointer to a CDoubleString class object; which may specify a minimum and maximum allowed double-precision floating-point value, whether the value is a required or optional stage command argument and whether leading and trailing delimiters can be skipped or not.

 

    

Returns

 

 

bool

true if the function successfully extracts a double string; in which case the function sets the CDoubleString member m_nReturnCode to a value of _RC_SUCCESS_.

 

Otherwise the function returns a value of false; which indicates an invalid or missing, required stage command argument. In this case the function sets the CDoubleString member m_nReturnCode to one of the following values:

 

m_nReturnCode

Meaning

 

 

_RC_NOT_FOUND_

The double string is missing from the stage command argument.

_RC_NOT_NUMERIC_

The double string contains non-numeric characters.

 

    

Messages

When the CDoubleString member m_bRequired is set to true and the argument is missing or invalid; ParseForDoubleString() will issue one of the following stage messages: 31, 32.

 

    

Usage

The following example shows how you might use the ParseForDoubleString() function to extract a double string from your stage command argument and convert it to a double-precision floating-point value.

 

bool CMyStage:Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // Access my argument.
    const char *pszArgument = pStage->Argument();
 
    CString szToken;
    CToken *pToken = new CToken( *this );
 
    if( *pszArgument )
    {
        ...
 
        CDoubleString *pDoubleString = new CdoubleString( *this );
 
        // Extract a double string.
        pDoubleString->m_pszSource = &pszArgument;
        pDoubleString->m_pszTarget = &szToken;
        pDoubleString->m_bRequired = true;
 
        if( m_pManager->ParseForDoubleString( m_pDoubleString ) )
        {
            // Covert the string to a double-precision floating-point value.
            if( !m_pManager->ConvertToDouble( m_pDoubleString ) ) 
                return( false );
 
            m_dbValue = m_pDoubleString->m_dbResult;
        }
        else
        return( false );
 
        ...
    }
 
    ...
 
    Return( true );
} 

 

 
bool CStageManager::ParseForCharacterString(
    _inout                                   CCharacterString *a_pCharString );
 

 

    

Purpose

Use ParseForCharacterString() to extract a delimited literal character string, hexadecimal string or binary string from your stage command argument.

 

ParseForCharacterString() uses the CCharacterString class object to extract the string from your stage command argument. The ParseForCharacterString() function, which can skip leading and trailing delimiters; extracts the string, converts it to an ASCII character value and stores the result at the address specified in the CCharacterString member m_pszTarget.

 

    

Parameters

 

 

CCharacterString*a_pCharString

[in,out] A pointer to a CCharacterString class object; which specifies the leading and trailing extraction delimiters and whether or not they can be skipped.

 

    

Returns

 

 

bool

true if the function successfully extracts a character string; in which case the function sets the CCharacterString member m_nReturnCode to a value of _RC_SUCCESS_ and the member m_nType to one of the following values:

 

m_nType

 

 

 

_STRING_TYPE_BINARY_

The string was specified as a binary character string.

_STRING_TYPE_CHARACTER_

The string was specified as a delimited ASCII character string.

_STRING_TYPE_HEXADECIMAL_

The string was specified as a hexadecimal character string.

 

Otherwise the function returns a value of false; which indicates an invalid or missing, required stage command argument. In this case the function sets the CCharacterString member m_nReturnCode to one of the following values:

 

m_nReturnCode

 

 

 

_RC_NOT_FOUND_

The string is missing from the stage command argument.

_RC_INVALID_FORMAT_

The string is not properly formed.

_RC_INVALID_HEX_CHAR_

The string contains an invalid hexadecimal character.

_RC_INVALID_LENGTH_

The string is specified as a binary or hexadecimal string and the number of characters is not a multiple of 2 or 8 characters in length, respectively. Or the length of the string is invalid; it must resolve to an ASCII character string that is at least as long as the minimum required length m_dwMinLength, and no longer than the maximum allowed length m_dwMaxLength.

_RC_INVALID_BIN_CHAR_

The string contains an invalid binary character.

_RC_NULL_STRING_

The CCharacterString member m_bNull is set to false; however, the string is of zero length.

_RC_INVALID_RANGE_

The string contains a character which resolves to a value of zero; the string must contain character definitions that are in the ASCII character range 1 – 255 (decimal).

 

    

Messages

When the CCharacterString member m_bRequired is set to true and the argument is missing or invalid; ParseForCharacterString() will issue one of the following stage messages: 12, 15, 17, 19, 22, 23, 37, 38, 39, 40, 43, 50.

 

    

Usage

The following example shows an edited excerpt from the CLiteral stage class commands’ Initialise() function. The portion of code shown; illustrates how the ParseForCharacterString() function is used to extract a delimited character string, hexadecimal string or binary string from your stage command argument.

 

bool CLiteral::Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // Access my argument.
    const char *pszArgument = m_pStage->Argument();
 
    // Set the default.
    CString szLiteral = "";
 
    if( *pszArgument )
    {
        ...
 
        if( *pszArgument )
        {
            CCharacterString *pCharacterString = new CCharacterString( *this ); 
 
            pCharacterString->m_bRequired = false;
            pCharacterString->m_pszSource = &pszArgument;
            pCharacterString->m_pszTarget = &szLiteral;
            pCharacterString->m_bNull = true;
 
            // If we cannot extract a character string, then the argument must be
            // a character range.
 
            if( !pManager->ParseForCharacterString( pCharacterString ) )
            {
                CCharacterRange *pCharacterRange = new CCharacterRange( *this );
 
                pCharacterRange->m_pszSource = &pszArgument;
                pCharacterRange->m_bRequired = true;
                pCharacterRange->m_bSkipTrailing = true;
                // Extract an expanded character range.
                pCharacterRange->m_bExpand = true;
                pCharacterRange->m_pszExpandedRange = &szLiteral;
                if( !pManager->ParseForCharacterRange( pCharacterRange ) )
                    return( false );
            }
        }
 
        // There should be no other arguments.
        if( *pszArgument )
        {
            m_pManager->StageMessage( *this, 33, _ERROR_, pszArgument );
            return( false );
        }
    }
 
    return( true );
}

 

 
bool CStageManager::ParseForRegExp(
    _in                             CProcess &a_Process,
    _inout                          CRegExpression *a_pRegExp,
    _in_opt                         bool a_bCaseSensitive = true );
 

 

    

Purpose

Use ParseForRegExp() to validate and assign a regular expression that has been extracted from your stage command argument.

 

During the initialisation phase of your stage; in or via a call from your stages’ Initialise() function; you extract the delimited character string which specifies the regular expression definition; using the ParseForCharacterString() function. Next, you present the buffer which contains that string to the ParseForRegExp() function; which will parse, evaluate and assign the expression. Then, during the runtime phase of your stage; in or via a call from your stages’ Go() function; you apply that expression to your stage input records; through a call to the RegExpMatch() function.

 

    

Parameters

 

 

CProcess &a_Process

[in] Your*this pointer (a CProcess base-class object).

 

CRegExpression *a_pRegExp

[in,out] A pointer to a CRegExpression class object; whose Expression member contains a pointer to a buffer that contains the regular expression to evaluate and assign.

 

bool a_bCaseSensitive

[in,opt] Set this option to true if the expression to be applied is case-sensitive, otherwise false; which indicates that the expression to be applied is non-case-sensitive; that is to say; if the expression contains a mixture of uppercase and lowercase characters; the expression and the content of an input record are compared in uppercase.

 

    

Returns

 

 

bool

true if the function successfully validates and extracts a regular expression, otherwise; false which indicates an invalid or missing expression element.

 

    

Messages

When an error occurs parsing the regular expression; ParseForRegExp() will issue the following stage message: 18.

 

    

Usage

The following example shows edited excerpts from the CBetween stage class definition and its stage class functions: Initialise() and Go(). The Initialise() function illustrates how you might extract a regular expression from your stage command argument and the Go() function demonstrates how you might implement regular expression processing on your input records.

 

// Class definition
 
class CBetween : public CProcess
{
    ...
 
    CStageManager *m_pManager;
    CStage *m_pStage;
 
    CString m_szRecord;
    DWORD m_dwFromType;
    CRegExpression *m_pFromRegExp;
    CString m_szFrom;
 
    enum m_eType { ..., m_eRegExp };
 
    ...
};
 
// Initialisation phase.
 
bool CBetween::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    // Access my argument.
    const char *pszArgument = m_pStage->Argument();
 
    // Perform any preprocessing required.
    if( !m_pManager->PreProcess( *this, &pszArgument ) )
        return( false );
 
    ...
 
    CCharacterString *pCharacterString = new CCharacterString( *this ); 
 
    // Extract the 'from' string.
    pCharacterString->m_pszSource = &pszArgument;
    pCharacterString->m_pszTarget = &m_szFrom;
    pCharacterString->m_bRequired = true;
    if( m_dwFromType == m_eString )
        pCharacterString->m_bNull = true;
    else
    pCharacterString->m_bNull = false;
 
    if( !m_pManager->ParseForCharacterString( pCharacterString ) )
        return( false );
 
    ...
 
    // Perform the regular expression validation.
    if( m_dwFromType == m_eRegExp ) )
    {
        m_pFromRegExp->m_RegExp.Expression = m_szFrom;
        if( !m_pManager->ParseForRegExp( *this, m_pFromRegExp, !m_pStage->Casei() ) )
            return( false );
    }
 
    ...
 
    return( true );
}
 
// Runtime phase.
 
DWORD CBetween::Go( void )
{
    ...
 
    // Ok, now lets read and process the primary input stream.
    for( ;; )
    {
        // If all my output streams are disconnected, then exit.
        if( !m_pStage->OutStreamsConnected() )
            break;
 
        if( !m_pManager->PeekRecord( *this, 0, &m_szRecord ) )
            break;
 
        ...
 
        else
        if( m_dwFromType == m_eRegExp )
        {
            if( m_pManager->RegExpMatch( m_pFromRegExp, m_szRecord ) )
            {
                ...
            }
        }
    
        ...
 
        // Write record to designated output sstream.
        m_pManager->WriteRecord( *this, dwStream, &m_szRecord );
    
        // Release the stage that we read from.
        m_pManager->ConsumeRecord( *this, 0 );
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::ParseForIntegerRange(
    _inout                                CIntegerRange *a_pIntRange );
 

 

    

Purpose

Use ParseForIntegerRange() to extract an integer range from your stage command argument.

 

ParseForIntegerRange() uses the CIntegerRange class object to extract an integer range from your stage command argument. The ParseForIntegerRange() function, which can skip leading and trailing delimiters, extracts the; from and to range values and stores them; as real integer values in the CIntegerString members m_lFrom and m_lTo, respectively.

 

To use the function; simply set the member m_nType to one of the following values:

 

m_nType

Meaning

 

 

eInput

The function will extract an integer range which describes an input record location and ending column or input range length.

eOuput

The function will extract an integer range which describes an output record location and ending column or output range length.

 

By default; ParseForIntegerRange() sets the starting column m_lFrom to the unsigned integer value of 1 and the ending column m_lTo to the unsigned integer value of _MAX_INT_.

 

There are two types of integer range; the first is a range which describes an input; a range of columns, words or fields of an input record on which to operate, and the second; which describes an output column position and range length; a starting and corresponding length of some piece of data to write to an output record.

 

The following definitions describe the possible patterns and their relative types:

 

Pattern

Input/output type

Type

 

 

 

loc-loc

input/output

A starting and ending column range that is relative the beginning of the record.

loc;loc

input/output

A starting and ending column range that is relative the beginning of the record.

-loc;loc

input

A starting column that is relative to the end of the record and an ending column that is relative to the beginning of the record.

loc;-loc

input

A starting column that is relative to the beginning of the record and an ending column that is relative to the end of the record.

-loc;-loc

input

A starting and ending column range that is relative to the end of the record.

loc

input/output

A single column that is relative to the beginning of the record.

-loc

input

A single column that is relative to the end of the record.

loc-*

input

A starting column that is relative to the beginning of the record and an ending column that represents the last column of the record.

loc;*

input

A starting column that is relative to the beginning of the record and an ending column that represents the last column of the record.

*-loc

input/output

A starting column which represents the first column of the record and an ending column that is relative to the beginning of the record.

*;loc

input/output

A starting column which represents the first column of the record and an ending column that is relative to the beginning of the record.

*;-loc

input

A starting column which represents the first column of the record and an ending column that is relative to the end of the record.

-loc;*

input

A starting column that is relative to the end of the record and an ending column that represents the last column of the record.

*-*

input

A starting column which represents the first column of the record and an ending column which represents the last column of the record.

*;*

input

A starting column which represents the first column of the record and an ending column which represents the last column of the record.

loc.n

input/output

A starting column that is relative to the beginning of the record and a range length; which is inclusive of the starting column.

 

    

Parameters

 

 

CIntegerRange *a_pIntRange

[in,out] A pointer to a CIntegerRange class object; which specifies the leading and trailing extraction delimiters and whether or not they can be skipped.

 

    

Returns

 

 

bool

true if the function successfully extracts an integer range; in which case the function sets the CIntegerRange member m_nReturnCode to a value of _RC_SUCCESS_ and the member m_nType to one of the following values:

 

m_nType              

Meaning

 

 

eTo

The value in member’s m_lFrom and m_lTo represent a starting column number and ending column number range, respectively.

eFor

The value in member’s m_lFrom and m_lTo represent a starting column number and range length; which is inclusive of the starting column, respectively.

eSingle

The value in member’s m_lFrom and m_lTo are the same; and represent a range that is one column in length.

 

Otherwise the function returns a value of false; which indicates an invalid or missing, required stage command argument. In this case the function sets the CIntegerRange member m_nReturnCode to one of the following values:

 

m_nReturnCode

Meaning

 

 

_RC_INVALID_FORMAT_

The character range is badly formed; it may contain non-numeric characters or it may be syntactically incorrect.

_RC_INVALID_RANGE_

The range may specify values that are outside the minimum and maximum values described by the members m_lFrom and m_lTo.

_RC_NOT_FOUND_

The character range is missing from the stage command argument.

 

     

Messages

When the CIntegerRange member m_bRequired is set to true and the argument is missing or invalid; ParseForIntegerRange() will issue one of the following stage messages: 4, 5, 9, 15, 20, 24, 25, 46, 51, 52, 60, 61, 62.

 

    

Usage

The following example shows an edited excerpt from the CSort stage class commands’ Initialise() function. The portion of code shown; illustrates how the ParseForIntegerRange() function is used to extract an integer range from your stage command argument.

 

bool CSort::Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // Access my argument.
    const char *pszArgument = m_pStage->Argument();
 
    if( *pszArgument )
    {
        CIntegerRange *pIntegerRange = new CIntegerRange( *this ); 
 
        ...
 
        pIntegerRange->m_pszSource = &pszArgument;
        pIntegerRange->m_bFromSigned = false;
        pIntegerRange->m_bToSigned = false;
        pIntegerRange->m_bRequired = true;
 
        // Loop through the groups that are defined.
        for( DWORD dwCount = 0; dwCount < _MAX_INT_; ++dwCount )
        {
            // If its the end of the argument..
            if( !*pszArgument )
                break;
 
            if( !m_pManager->ParseForIntegerRange( pIntegerRange ) )
                return( false );
 
            ...
         }
    }
 
    ...
 
    return( true );
}

 

 
bool CStageManager::ParseForCharacter(
    _inout                             CCharacterString *a_pCharString );
 

 

    

Purpose

Use ParseForCharacter() to extract an ASCII character, hexadecimal character or binary character from your stage command argument.

 

ParseForCharacter() uses the CCharacterString class object to extract a character definition from your stage command argument. The ParseForCharacter() function, which can skip leading and trailing delimiters; extracts the character definition and stores it as an ASCII character at the address specified in the CCharacterString member m_pszTarget.

 

    

Parameters

 

 

CCharacterString *a_pCharString

[in,out] A pointer to a CCharacterString class object; which specifies the leading and trailing extraction delimiters and whether or not they can be skipped.

 

    

Returns

 

 

bool

true if the function successfully extracts a character definition; in which case the function sets the CCharacterString member m_nReturnCode to a value of _RC_SUCCESS_ and the member m_nType to one of the following values:

 

m_nType

 

 

 

_STRING_TYPE_BINARY_

The string was specified as a binary character string.

_STRING_TYPE_CHARACTER_

The string was specified as a delimited ASCII character string.

_STRING_TYPE_HEXADECIMAL_

The string was specified as a hexadecimal character string.

 

Otherwise the function returns a value of false; which indicates an invalid or missing, required stage command argument. In this case the function sets the CCharacterString member m_nReturnCode to one of the following values:

 

m_nReturnCode

 

 

 

_RC_NOT_FOUND_

The character is missing from the stage command argument.

_RC_INVALID_HEX_CHAR_       

The character is an invalid hexadecimal character.

_RC_INVALID_BIN_CHAR_

The character is an invalid binary character.

_RC_INVALID_RANGE_

The character represents a value of zero; the character must resolve to an ASCII definition that is in the range 1 – 255 (decimal).

_RC_INVALID_LENGTH_

The character is specified as a binary or hexadecimal character and the number of characters is not a multiple of 2 or 8 characters in length.

 

    

Messages

When the CCharacterString member m_bRequired is set to true and the argument is missing or invalid; ParseForCharacter() will issue one of the following stage messages: 12, 15, 35, 37, 38, 39, 40, 43, 47, 48, 50

    

Usage

The following example shows an edited excerpt from the CPad stage class commands’ Initialise() function. The portion of code shown; illustrates how the ParseForCharacter() function is used to extract a character from your stage command argument.

 

bool CPad::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    ...
 
    // Access my argument.
    const char *pszArgument = m_pStage->Argument();
 
    // Set the default.
    m_szChars = " ";
 
    ...
 
    if( *pszArgument )
    {
        // Save the current pointer.
        const char *pszSave = pszArgument;
 
        // Extract the next token.
        m_pToken->m_pszSource = &pszArgument;
        m_pToken->m_pszTarget = &szToken;
 
        if( !m_pManager->ParseForToken( m_pToken ) )
            return( false );
 
        if( szToken.CompareNoCase( "SPACE" ) )
        {
            // Restore the pointer.
            pszArgument = pszSave;
 
            // Extract the pad character.
            m_pCharacterString->m_pszSource = &pszArgument;
            m_pCharacterString->m_pszTarget = &m_szChars;
            m_pCharacterString->m_bRequired = true;
 
            if( !m_pManager->ParseForCharacter( m_pCharacterString ) )
                return( false );
        }
 
        // There should be no other arguments.
        if( *pszArgument )
        {
            m_pManager->StageMessage( *this, 33, _ERROR_, pszArgument );
            return( false );
        }
    }
 
    return( true );
}

 

 
bool CStageManager::ParseForCharacterRange(
    _inout                                  CCharacterRange *a_pCharRange );
 

 

    

Purpose

Use ParseForCharacterRange() to extract an ASCII character range, hexadecimal character range or binary character range from your stage command argument.

 

ParseForCharacterRange() uses the CCharacterRange class object to extract a character range from your stage command argument. The ParseForCharacterRange() function, which can skip leading and trailing delimiters, extracts the; from and to range values and stores them in the CCharacterRange members m_szFrom and m_szTo, respectively.

 

The following definitions describe the possible patterns and their relative types:

 

Pattern

Type

 

 

char/SPACE

A single ASCII character, hexadecimal character, binary character or the synonym; SPACE.

char/SPACE.n

A range which starts with an ASCII character, hexadecimal character, binary character or the synoym; SPACE and n characters long.

char1/SPACE-char2/SPACE

A range which starts with an ASCII character, hexadecimal character, binary character or the synoym; SPACE and ends with an ASCII character, hexadecimal character, binary character or the synoym; SPACE

 

When you set the CCharacterRange member m_bExpand to true; ParseForCharacterRange() will fill the buffer pointed to by the member m_pszExpandedRange with an expanded version of the range. That is to say; if the stage command argument comprises the character range: A-G, the buffer will contain the expanded string: ABCDEFG.

 

    

Parameters

 

 

CCharacterRange *a_pCharRange

[in,out] A pointer to a CCharacterRange class object; which specifies the leading and trailing extraction delimiters and whether or not they can be skipped.

 

    

Returns

 

 

bool

true if the function successfully extracts a character range; in which case the function sets the CCharacterRange member m_nReturnCode to a value of _RC_SUCCESS_.

 

Otherwise the function returns a value of false; which indicates an invalid or missing, required stage command argument. In this case the function sets the CCharacterRange member m_nReturnCode to one of the following values:

 

m_nReturnCode

Meaning

 

 

_RC_INVALID_BIN_CHAR_

The character specified is not a valid binary character.

_RC_INVALID_FORMAT_

The character range is badly formed; it may contain non-numeric characters or it may be syntactically incorrect.

_RC_INVALID_HEX_CHAR_

The character sepcified is not a valid hexadecimal character.

_RC_INVALID_LENGTH_

The number of digits for either a hexadecimal or binary character must be a multiple of two or eight, respectively.

_RC_NOT_FOUND_

The character range is missing from the stage command argument.

_RC_NOT_NUMERIC_

The integer string comprises one or more non numeric characters.

 

    

Messages

When the CCharacterRange member m_bRequired is set to true and the argument is missing or invalid; ParseForIntegerRange() will issue one of the following stage messages: 9, 12, 20, 35, 40, 47, 48, 50, 60, 61.

 

    

Usage

The following example shows an edited excerpt from the CLiteral stage class commands’ Initialise() function. The portion of code shown; illustrates how the ParseForCharacterRange() function is used to extract a character range from your stage command argument.

 

bool CLiteral::Initialise( void )

{

    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // Access my argument.
    const char *pszArgument = m_pStage->Argument();

 

    // Set the default.

    CString szLiteral = "";

 

    if( *pszArgument )

    {

        ...

 

        if( *pszArgument )

        {

            CCharacterString *pCharacterString = new CCharacterString( *this ); 

 

            pCharacterString->m_bRequired = false;
            pCharacterString->m_pszSource = &pszArgument;
            pCharacterString->m_pszTarget = &szLiteral;
            pCharacterString->m_bNull = true;

 

            // If we cannot extract a character string, then the argument must be

            // a character range.

 

            if( !pManager->ParseForCharacterString( pCharacterString ) )

            {

                CCharacterRange *pCharacterRange = new CCharacterRange( *this ); 

 

                pCharacterRange->m_pszSource = &pszArgument;
                pCharacterRange->m_bRequired = true;
                pCharacterRange->m_bSkipTrailing = true;

                // Extract an expanded character range.

                pCharacterRange->m_bExpand = true;
                pCharacterRange->m_pszExpandedRange = &szLiteral;

                if( !pManager->ParseForCharacterRange( pCharacterRange ) )

                    return( false );

            }

        }

 

        // There should be no other arguments.

        if( *pszArgument )

        {

            m_pManager->StageMessage( *this, 33, _ERROR_, pszArgument );

            return( false );

        }

    }

 

    return( true );

}

 

 
bool CStageManager::ConvertToInteger(
    _inout                            CIntegerString *a_pIntString );
 

 

    

Purpose

Use ConvertToInteger() to convert an integer string to a (long) integer value.

 

ConvertToInteger() validates and converts the integer string contained in the CIntegerString member m_pszTarget to a (long) integer value and stores that result in the CIntegerString member m_lResult.

 

    

Parameters

 

 

CIntegerString *a_pIntString

[in,out] A pointer to a CIntegerString class object; which specifies the maximum and minimum signed and unsigned integer values.

 

    

Returns

 

 

bool

true if the function successfully converts the integer string to a real (long) integer value; in which case the function stores that value in the CIntegerString member m_lResult and sets the CIntegerString member m_nReturnCode to a value of _RC_SUCCESS_.

 

Otherwise the function returns a value of false; which indicates an out of range integer or invalid integer string argument. In this case the function sets the CIntegerString member m_nReturnCode to one of the following values:

 

m_nReturnCode

Meaning

 

 

_RC_INVALID_RANGE_

The integer specified is outside the minimum required and maximum allowed signed or unsigned integer value.

_RC_NOT_NUMERIC_

The integer string comprises one or more non numeric characters.

 

    

Messages

When the CIntegerString member m_bRequired is set to true and the argument is invalid; ConvertToInteger() will issue one of the following stage messages: 24, 51, 52, 62.

 

    

Usage

The following example shows an edited excerpt from the CDuplicate stage class commands’ Initialise() function. The portion of code shown; illustrates how the ParseForIntegerString() and ConvertToInteger() functions are used to extract an integer string from your stage command argument and convert it to a real (long) integer value.

 

bool CDuplicate::Initialise( void )
{

    // Access the manager.

    CStageManager *pManager = Manager();

    // Access my stage.

    CStage *pStage = pManager->GetStage( *this );

 
    ...
 
    // Access my argument.
    const char *pszArgument = pStage->Argument();
 
    // Set defaults.
    m_lCopies = 1;
    
    ...
 
    if( *pszArgument )
    {
        CString szToken;
        CToken *pToken = new CToken( *this );
        CIntegerString *pIntegerString = new CIntegerString( *this ); 
 
        pIntegerString->m_pszSource = &pszArgument;
        pIntegerString->m_pszTarget = &szToken;
        pIntegerString->m_dwMinUnsignedValue = 0;
        pIntegerString->m_dwMaxUnsignedValue = _MAX_INT_ - 1;
 
        // Try to extract an integer string.
        if( pManager->ParseForIntegerString( pIntegerString ) )
        {
            pIntegerString->m_bRequired = true;
            if( !pManager->ConvertToInteger( pIntegerString ) )
               return( false );
 
            m_lCopies = pIntegerString->m_lResult;
        }
        else
        {
            ...
        }
 
        // There should be no other arguments.
        if( *pszArgument )
        {
            pManager->StageMessage( *this, 33, _ERROR_, pszArgument );
            return( false );
        }
    }
 
    ...
 
    return( true );

}

 

 
bool CStageManager::ConvertToDouble(
    _inout                           CDoubleString *a_pDblString );
 

 

    

Purpose

Use ConvertToDouble() to convert a double string to a double-precision floating-point value.

 

ConvertToDouble() validates and converts the double string contained in the CDoubleString member m_pszTarget to a double-precision floating-point value and stores that result in the CDoubleString member m_dbResult.

 

    

Parameters

 

 

CDoubleString *a_pDblString

[in,out] A pointer to a CDoubleString class object; which specifies the maximum and minimum double-precision floating-point values.

 

    

Returns

 

 

bool

true if the function successfully converts the double string to a real double-precision floating-point value; in which case the function stores that value in the CDoubleString member m_dbResult and sets the CDoubleString member m_nReturnCode to a value of _RC_SUCCESS_.

 

Otherwise the function returns a value of false; which indicates an out of range double-precision floating-point or invalid double string argument. In this case the function sets the CDoubleString member m_nReturnCode to one of the following values:

 

m_nReturnCode

Meaning

 

 

_RC_INVALID_RANGE_

The double-precision floating-point specified is outside the minimum required and maximum allowed value.

_RC_NOT_NUMERIC_

The double string comprises one or more non numeric characters.

 

    

Messages

When the CDoubleString member m_bRequired is set to true and the argument is invalid; ConvertToDouble() will issue one of the following stage messages: 32, 42.

 

    

Usage

The following example shows how you might use the ConvertToDouble() function to convert it to a double-precision floating-point value.

 

bool CMyStage:Initialise( void )
{
    // Access the manager.
    CStageManager *pManager = Manager();
    // Access my stage.
    CStage *pStage = pManager->GetStage( *this );
 
    ...
 
    // Access my argument.
    const char *pszArgument = pStage->Argument();
 
    CString szToken;
    CToken *pToken = new CToken( *this );
 
    if( *pszArgument )
    {
        ...
 
        CDoubleString *pDoubleString = new CdoubleString( *this );
 
        // Extract a double string.
        pDoubleString->m_pszSource = &pszArgument;
        pDoubleString->m_pszTarget = &szToken;
        pDoubleString->m_bRequired = true;
 
        if( m_pManager->ParseForDoubleString( m_pDoubleString ) )
        {
            // Covert the string to a double-precision floating-point value.
            if( !m_pManager->ConvertToDouble( m_pDoubleString ) ) 
                return( false );
 
            m_dbValue = m_pDoubleString->m_dbResult;
        }
        else
        return( false );
 
        ...
    }
 
    ...
 
    Return( true );
}

 

 
void CStageManager::ExtractColumnRange(
    _inout                              CExtractRange *a_pRange );
 

 

    

Purpose

Use ExtractColumnRange() to extract a column delimited substring from an input stream record.

 

During the initialisation phase of your stage; in or via a call from your stages’ Initialise() function; you first make a call to the ParseForIntegerRange() function to extract an integer range definition from your stage command argument. This range defines the columns that you want to extract from each input stream record during your runtime phase. Next, you pre-fill the CExtractRange class object with the values contained in the CIntegerString class object. Finally during your runtime phase, in or via call from your stages’ Go() function; you make a call to the ExtractColumnRange() function to determine the starting m_lFrom and ending m_lTo columns of the specified column range.

 

ExtractFieldRange() extracts the substring which starts at column number m_lFrom, up to and including column number m_lTo and stores the extracted string in the buffer pointed to by the member m_pszTarget.

 

    

Parameters

 

 

CExtractRange *a_pRange

[in,out] A pointer to a CExtractRange class object; which specifies the starting column range position m_lFrom and ending column position m_lTo.

 

    

Returns

 

void

 

    

Messages

None

 

    

Usage

The following example shows a simplified version of the CTranslate stage commands’ Go() function. The code illustrates how the ExtractColumnRange() function can be used to isolate and extract a range of columns from an input stream record.

 

DWORD CTranslate::Go( void )
{
    // Pre-load the range object with the common default values used by all three range types.
    CString szRange;
    CExtractRange *pRange = new CExtractRange;
    pRange->m_pszSource = &m_szRecord;
    pRange->m_pszTarget = &szRange;
    pRange->m_bExtractRange = false;
    pRange->m_bResolveRange = true;
 
    // Access my primary output stream.
    COutStream *pPriOutStream = m_pStage->GetOutStream( 0 );
 
    // Ok, now lets read and process our input streams..
    for( ;; )
    {
        // If my primary output stream is disconnected, then exit.
        if( pPriOutStream->IsDisConnected() )
            break;
 
        if( !m_pManager->PeekRecord( *this, 0, &m_szRecord ) )
            break;
 
        // Apply the translate table to the record.
 
        // Extract the simple column range.
        if( m_bInpRange )
        {
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractColumnRange( pRange );
        }
        else
        // Extract the field range.
        if( m_bInpField )
        {
            pRange->m_szDelimiter = m_szFieldSeperator;
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractFieldRange( pRange );
        }
        else
        // Extract the word range.
        if( m_bInpWord )
        {
            pRange->m_szDelimiter = m_szWordSeperator;
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractWordRange( pRange );
        }
 
        // Using each byte of the record as an index into the translate table; replace that byte with the
        // corresponding translate table entry.
        if( pRange->m_lFrom >= 0 && pRange->m_lFrom <= m_szRecord.GetLength() )
        {
            const char *pszRecord = ( LPCTSTR )m_szRecord + pRange->m_lFrom;
            for( int nIndex = pRange->m_lFrom; nIndex <= pRange->m_lTo && *pszRecord; ++nIndex, ++pszRecord )
                m_szRecord.SetAt( nIndex, m_szTransTable.GetAt( ( BYTE )( *pszRecord ) - 1 ) );
        }
 
        // Write the record to the primary output stream.
        if( !m_pManager->WriteRecord *this, 0, &m_szRecord ) )
            break;
 
        // Release the stage that we read from.
        m_pManager->ConsumeRecord( *this, 0 );
    }
 
    // Release the allocation.
    delete pRange;
 
    return( _RC_SUCCESS_ );
}

 

 
void CStageManager::ExtractWordRange(
    _inout                            CExtractRange *a_pRange );
 

 

    

Purpose

Use ExtractWordRange() to extract a word delimited substring from an input stream record.

 

During the initialisation phase of your stage; in or via a call from your stages’ Initialise() function; you first make a call to the ParseForIntegerRange() function to extract an integer range definition from your stage command argument. This range defines the words that you want to extract from each input stream record during your runtime phase. Next, you pre-fill the CExtractRange class object with the values contained in the CIntegerString class object. Finally during your runtime phase, in or via call from your stages’ Go() function; you make a call to the ExtractWordRange() function to determine the starting m_lFrom and ending m_lTo columns of the specified word range.

 

ExtractWordRange() extracts the substring which starts at word number m_lFrom, up to and including word number m_lTo and stores the extracted string in the buffer pointed to by the member m_pszTarget.

 

    

Parameters

 

 

CExtractRange *a_pRange

[in,out] A pointer to a CExtractRange class object; which specifies the starting word range position m_lFrom and ending range position m_lTo.

 

    

Returns

 

void

 

    

Messages

None

 

    

Usage

The following example shows a simplified version of the CTranslate stage commands’ Go() function. The code illustrates how the ExtractWordRange() function can be used to isolate and extract a range of words from an input stream record.

 

DWORD CTranslate::Go( void )
{
    // Pre-load the range object with the common default values used by all three range types.
    CString szRange;
    CExtractRange *pRange = new CExtractRange;
    pRange->m_pszSource = &m_szRecord;
    pRange->m_pszTarget = &szRange;
    pRange->m_bExtractRange = false;
    pRange->m_bResolveRange = true;
 
    // Access my primary output stream.
    COutStream *pPriOutStream = m_pStage->GetOutStream( 0 );
 
    // Ok, now lets read and process our input streams..
    for( ;; )
    {
        // If my primary output stream is disconnected, then exit.
        if( pPriOutStream->IsDisConnected() )
            break;
 
        if( !m_pManager->PeekRecord( *this, 0, &m_szRecord ) )
            break;
 
        // Apply the translate table to the record.
 
        // Extract the simple column range.
        if( m_bInpRange )
        {
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractColumnRange( pRange );
        }
        else
        // Extract the field range.
        if( m_bInpField )
        {
            pRange->m_szDelimiter = m_szFieldSeperator;
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractFieldRange( pRange );
        }
        else
        // Extract the word range.
        if( m_bInpWord )
        {
            pRange->m_szDelimiter = m_szWordSeperator;
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractWordRange( pRange );
        }
 
        // Using each byte of the record as an index into the translate table; replace that byte with the
        // corresponding translate table entry.
        if( pRange->m_lFrom >= 0 && pRange->m_lFrom <= m_szRecord.GetLength() )
        {
            const char *pszRecord = ( LPCTSTR )m_szRecord + pRange->m_lFrom;
            for( int nIndex = pRange->m_lFrom; nIndex <= pRange->m_lTo && *pszRecord; ++nIndex, ++pszRecord )
                m_szRecord.SetAt( nIndex, m_szTransTable.GetAt( ( BYTE )( *pszRecord ) - 1 ) );
        }
 
        // Write the record to the primary output stream.
        if( !m_pManager->WriteRecord *this, 0, &m_szRecord ) )
            break;
 
        // Release the stage that we read from.
        m_pManager->ConsumeRecord( *this, 0 );
    }
 
    // Release the allocation.
    delete pRange;
 
    return( _RC_SUCCESS_ );
}

 

 
void CStageManager::ExtractFieldRange(
    _inout                             CExtractRange *a_pRange );
 

 

    

Purpose

Use ExtractFieldRange() to extract a field delimited substring from an input stream record.

 

During the initialisation phase of your stage; in or via a call from your stages’ Initialise() function; you first make a call to the ParseForIntegerRange() function to extract an integer range definition from your stage command argument. This range defines the fields that you want to extract from each input stream record during your runtime phase. Next, you pre-fill the CExtractRange class object with the values contained in the CIntegerString class object. Finally during your runtime phase, in or via call from your stages’ Go() function; you make a call to the ExtractFieldRange() function to determine the starting m_lFrom and ending m_lTo columns of the specified field range.

 

ExtractFieldRange() extracts the substring which starts at field number m_lFrom, up to and including field number m_lTo and stores the extracted string in the buffer pointed to by the member m_pszTarget.

 

    

Parameters

 

 

CExtractRange *a_pRange

[in,out] A pointer to a CExtractRange class object; which specifies the starting field range position m_lFrom and ending range position m_lTo.

 

    

Returns

 

void

 

    

Messages

None

 

    

Usage

The following example shows a simplified version of the CTranslate stage commands’ Go() function. The code illustrates how the ExtractFieldRange() function can be used to isolate and extract a range of fields from an input stream record.

 

DWORD CTranslate::Go( void )
{
    // Pre-load the range object with the common default values used by all three range types.
    CString szRange;
    CExtractRange *pRange = new CExtractRange;
    pRange->m_pszSource = &m_szRecord;
    pRange->m_pszTarget = &szRange;
    pRange->m_bExtractRange = false;
    pRange->m_bResolveRange = true;
 
    // Access my primary output stream.
    COutStream *pPriOutStream = m_pStage->GetOutStream( 0 );
 
    // Ok, now lets read and process our input streams..
    for( ;; )
    {
        // If my primary output stream is disconnected, then exit.
        if( pPriOutStream->IsDisConnected() )
            break;
 
        if( !m_pManager->PeekRecord( *this, 0, &m_szRecord ) )
            break;
 
        // Apply the translate table to the record.
 
        // Extract the simple column range.
        if( m_bInpRange )
        {
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractColumnRange( pRange );
        }
        else
        // Extract the field range.
        if( m_bInpField )
        {
            pRange->m_szDelimiter = m_szFieldSeperator;
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractFieldRange( pRange );
        }
        else
        // Extract the word range.
        if( m_bInpWord )
        {
            pRange->m_szDelimiter = m_szWordSeperator;
            pRange->m_lFrom = m_lFrom;
            pRange->m_lTo = m_lTo;
            m_pManager->ExtractWordRange( pRange );
        }
 
        // Using each byte of the record as an index into the translate table; replace that byte with the
        // corresponding translate table entry.
        if( pRange->m_lFrom >= 0 && pRange->m_lFrom <= m_szRecord.GetLength() )
        {
            const char *pszRecord = ( LPCTSTR )m_szRecord + pRange->m_lFrom;
            for( int nIndex = pRange->m_lFrom; nIndex <= pRange->m_lTo && *pszRecord; ++nIndex, ++pszRecord )
                m_szRecord.SetAt( nIndex, m_szTransTable.GetAt( ( BYTE )( *pszRecord ) - 1 ) );
        }
 
        // Write the record to the primary output stream.
        if( !m_pManager->WriteRecord *this, 0, &m_szRecord ) )
            break;
 
        // Release the stage that we read from.
        m_pManager->ConsumeRecord( *this, 0 );
    }
 
    // Release the allocation.
    delete pRange;
 
    return( _RC_SUCCESS_ );
}

  

 
bool RegExpMatch(
    _in           CRegExpression *a_pRegExp,
    _in           CString &a_szSource );
 

 

    

Purpose

Use RegExpMatch() to compare a regular expression against the contents of the specified buffer a_szSource.

 

During the initialisation phase of your stage; in or via a call from your stages’ Initialise() function; you extract the delimited character string which specifies the regular expression definition; using the ParseForCharacterString() function. Next, you present the buffer which contains that string to the ParseForRegExp() function; which will parse, evaluate and assign the expression. Then, during the runtime phase of your stage; in or via a call from your stages’ Go() function; you apply that expression to your stage input records; through a call to the RegExpMatch() function.

 

    

Parameters

 

 

CregExpression *a_pRegExp

[in] A pointer to a CRegExpression class object; which specifies the regular expression to apply.

 

CString &a_szSource

[in] The address of a buffer which contains the text to match.

 

    

Returns

 

bool

true if the regular expression matches the contents of the buffer pointed to by a_szSource, otherwise; false which indicates that the regular expression does not match.

 

    

Messages

None

 

    

Usage

The following example shows edited excerpts from the CBetween stage class definition and its stage class functions: Initialise() and Go(). The Initialise() function illustrates how you might extract a regular expression from your stage command argument and the Go() function demonstrates how you might implement regular expression processing on your input records.

 

// Class definition
 
class CBetween : public CProcess
{
    ...
 
    CStageManager *m_pManager;
    CStage *m_pStage;
 
    CString m_szRecord;
    DWORD m_dwFromType;
    CRegExpression *m_pFromRegExp;
    CString m_szFrom;
 
    enum m_eType { ..., m_eRegExp };
 
    ...
};
 
// Initialisation phase.
 
bool CBetween::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    // Access my argument.
    const char *pszArgument = m_pStage->Argument();
 
    // Perform any preprocessing required.
    if( !m_pManager->PreProcess( *this, &pszArgument ) )
        return( false );
 
    ...
 
    CCharacterString *pCharacterString = new CCharacterString( *this ); 
 
    // Extract the 'from' string.
    pCharacterString->m_pszSource = &pszArgument;
    pCharacterString->m_pszTarget = &m_szFrom;
    pCharacterString->m_bRequired = true;
    if( m_dwFromType == m_eString )
        pCharacterString->m_bNull = true;
    else
    pCharacterString->m_bNull = false;
 
    if( !m_pManager->ParseForCharacterString( pCharacterString ) )
        return( false );
 
    ...
 
    // Perform the regular expression validation.
    if( m_dwFromType == m_eRegExp ) )
    {
        m_pFromRegExp->m_RegExp.Expression = m_szFrom;
        if( !m_pManager->ParseForRegExp( *this, m_pFromRegExp, !m_pStage->Casei() ) )
            return( false );
    }
 
    ...
 
    return( true );
}
 
// Runtime phase.
 
DWORD CBetween::Go( void )
{
    ...
 
    // Ok, now lets read and process the primary input stream.
    for( ;; )
    {
        // If all my output streams are disconnected, then exit.
        if( !m_pStage->OutStreamsConnected() )
            break;
 
        if( !m_pManager->PeekRecord( *this, 0, &m_szRecord ) )
            break;
 
        ...
 
        else
        if( m_dwFromType == m_eRegExp )
        {
            if( m_pManager->RegExpMatch( m_pFromRegExp, m_szRecord ) )
            {
                ...
            }
        }
    
        ...
 
        // Write record to designated output sstream.
        m_pManager->WriteRecord( *this, dwStream, &m_szRecord );
    
        // Release the stage that we read from.
        m_pManager->ConsumeRecord( *this, 0 );
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool PatternMatch(
    _in            const char *a_pszPattern,
    _in            const char *a_pszSource );
 

 

    

Purpose

Use PatternMatch() to compare a pattern of characters against the contents of the specified buffer a_pszSource.

 

The pattern consists of a sequence of characters; any which may be the wildcard characters; ? and *. Where ? represents any single matching character and * represents any one or more matching characters.

 

    

Parameters

 

 

const char *a_pszPattern

[in] The address of a buffer which contains the pattern to match.

 

const char *a_pszSource

[in] The address of a buffer which contains the text to match.

 

    

Returns

 

bool

true if the pattern matches the contents of the buffer pointed to by a_pszSource, otherwise; false which indicates that the pattern does not match.

 

    

Messages

None

 

    

Usage

The following example shows an edited excerpt from the CTolabel stage class commands’ Go() function. The portion of code shown; illustrates how you can compare the contents of an input record with a user defined pattern.

 
DWORD CTolabel::Go( void )
{
    ...
 
    bool bFound = false;
    DWORD dwStream = 0;
 
    // Ok, now lets read and process our input streams..
    for( ;; )
    {
        // If all my output streams are disconnected, then exit.
        if( !m_pStage->OutStreamsConnected() )
            break;
 
        if( !m_pManager->PeekRecord( *this, 0, &m_szRecord ) )
        {
 
            // If the label has not yet been found, perform the search.
            if( !bFound )
            {
                ...
 
                else
                if( m_dwType == m_ePattern )
                {
                    if( m_pManager->PatternMatch( m_szLabel, m_szRecord ) )
                    {
                        bFound = true;
                        dwStream = 1;
                    }
                }
                else
                if( m_dwType == m_eRegExp )
                {
                    if( m_pManager->RegExpMatch( m_pRegExp, m_szRecord ) )
                    {
                        bFound = true;
                        dwStream = 1;
                    }
                }
            }
 
            // Write the record to the given output stream.
            if( !m_pManager->WriteRecord( *this, dwStream, &m_szRecord ) && dwStream )
                break;
 
            // Release the stage that we read from.
            m_pManager->ConsumeRecord( *this, 0 );
        }
    }
 
    return( _RC_SUCCESS_ );
}

 

 
bool CStageManager::SetStatus(
    _inout                     CStageInitInfo *a_pInfo );
 

 

    

Purpose

Use SetStatus() to inform the StageManager of the success or failure of your stage initialisation phase.

 

SetStatus() is the function through which your stage informs the StageManager of the success or failure of your stages’ initialisation phase; by setting a value of true or false in the CStageInitInfo member m_bReturnCode. The function causes your stage to become suspended until the StageManager has received and inspected this initialisation phase return code from all of the stages in the pipeline. If any stage reports a failed initialisation; the StageManager passes back a value of false, indicating that your stage should terminate immediately; otherwise it returns a value of true indicating that your stage should continue onto its runtime phase.

 

    

Parameters

 

 

CStageInitInfo *a_pInfo

[in,out] A pointer to a CStageInitInfo class object.

 

    

Returns

 

 

bool

true if your stage should continue onto its runtime phase, otherwise; false which indicates that your stage should terminate immediately.

 

    

Messages

None

 

    

Usage

 

DWORD BeginStage( CStageInitInfo *a_pInfo )

{

    AFX_MANAGE_STATE( AfxGetStaticModuleState() );

 

    // Instantiate the CStage class object.

    CLookup lookup( a_pInfo );

    // Perform initialisation phase processing.

    a_pInfo->m_bReturnCode = lookup.Initialise();
    // Inform the manager of the initialisation phase result and if
    // this or any other stage has reported an error, then terminate processing.

    if( !a_pInfo->Manager()->SetStatus( a_pInfo ) )

        return( _RC_FAIL_ );

    // Otherwise; proceed to our runtime phase.

    return( lookup.Go() );

}

 

RexxExitContext *CStageManager::GetRexxExitContext( void );

 

    

Purpose

Use GetRexxExitContext() to get the RexxExitContext object that references the instantiated ooRexx environment launched by Pipelines.

 

GetRexxExitContext() is the function through which your stage accesses the services that are specific to this ooRexx exit call, which includes; access to variables in the caller’s variable context. In other words, in order to communicate with ooRexx and be able to read from, write to, create and destroy ooRexx variables, stems and arrays; you must first call this function to acquire an interface exit object.

 

    

Parameters

 

 

void

 

    

Returns

 

 

RexxExitContext

A pointer to an ooRexx exit context object.

 

    

Messages

None

 

    

Usage

The following example shows an edited excerpt from the CStageManager class GetRexxArraySize() function. The portion of code shown; illustrates how to acquire the ooRexx exit context in order to determine the size of the array specified by the argument a_pszName.

 

DWORD CStageManager::GetRexxArraySize( const char *a_pszName )
{
    DWORD dwSize = 0;
    RexxThreadContext *pThreadContext;
 
    // Through the exit context; obtain the ooRexx thread context.
    if( GetRexxExitContext()->threadContext->instance->AttachThread( &pThreadContext ) )
    {
        CString szName = a_pszName;
        // Convert the name of the array to uppercase.
        CStringToUpper( &szName );
 
        const char *pszName = szName;
 
        // Get a pointer to the directory that contains the array.
        RexxObjectPtr ObjPtr = pThreadContext->DirectoryAt( GetRexxDirectoryObject(), pszName );
        if( ObjPtr != NULLOBJECT )
        {
            CString szItem;
 
            // Ensure that it is indeed an array object.
            if( pThreadContext->IsArray( ObjPtr ) )
            {
                // Get the size of the array
                RexxArrayObject arrayPtr = ( RexxArrayObject )ObjPtr;
                dwSize = ( DWORD ) pThreadContext->ArraySize( arrayPtr );
            }
        }
 
        // Release the thread.
        pThreadContext->DetachThread();
    }
 
    // Return the size of the array.
    return( dwSize );
}

 

RexxDirectoryObject CStageManager::GetRexxDirectoryObject( void );

 

    

Purpose

Use GetRexxtDirectoryObject() to access the ooRexx directory object that contains all of the variables, stems and arrays that are currently defined.

 

    

Parameters

 

 

void

 

    

Returns

 

 

RexxDirectoryObject

An ooRexx directory object.

 

    

Messages

None

 

    

Usage

The following example shows an edited excerpt from the CStageManager class GetRexxArraySize() function. The portion of code shown; illustrates how to access the ooRexx Directory Object that contains a copy of all of the ooRexx variables that are currently defined; in order to determine the size of the array specified by the argument a_pszName.

 

DWORD CStageManager::GetRexxArraySize( const char *a_pszName )
{
    DWORD dwSize = 0;
    RexxThreadContext *pThreadContext;
 
    // Through the exit context; obtain the ooRexx thread context.
    if( GetRexxExitContext()->threadContext->instance->AttachThread( &pThreadContext ) )
    {
        CString szName = a_pszName;
        // Convert the name of the array to uppercase.
        CStringToUpper( &szName );
 
        const char *pszName = szName;
 
        // Get a pointer to the directory that contains the array.
        RexxObjectPtr ObjPtr = pThreadContext->DirectoryAt( GetRexxDirectoryObject(), pszName );
        if( ObjPtr != NULLOBJECT )
        {
            CString szItem;
 
            // Ensure that it is indeed an array object.
            if( pThreadContext->IsArray( ObjPtr ) )
            {
                // Get the size of the array
                RexxArrayObject arrayPtr = ( RexxArrayObject )ObjPtr;
                dwSize = ( DWORD ) pThreadContext->ArraySize( arrayPtr );
            }
        }
 
        // Release the thread.
        pThreadContext->DetachThread();
    }
 
    // Return the size of the array.
    return( dwSize );

}

 

 

DWORD CStageManager::GetRexxVariable(

    _in                               const char *a_pszName,

    _out                              CString *a_pszValue );

 

 

    

Purpose

Use GetRexxVariable() to obtain the value of the ooRexx variable, specified by; a_pszName.

 

GetRexxVariable() can be used to obtain the value of a simple ooRexx variable, stem entry or array entry. In the case of a stem entry; you must specify the name of the entry; with each index in that name separated by a period (.), for example mystem.i.j. In the case of an array entry; you must specify the name of the entry; with each index in that name enclosed in square brackets ([]), for example myarray[i][j]. The function will insert the value of the specified entry into the CString object pointed to by a_pszValue.

 

    

Parameters

 

 

a_pszName

[in] A constant character pointer to the name of the ooRexx variable.

 

a_pszValue

[out] A pointer to a CString class object; which will be filled with the value of the ooRexx variable specified by a_pszName.

 

    

Returns

 

 

DWORD

_RC_REXX_SUCCESS_ if the variable is a currently defined ooRexx variable, in which case; the CString pointed to by a_pszValue is filled with the contents of the specified ooRexx variable, otherwise, the function returns _RC_REXX_VARIABLE_NOT_FOUND_ and the contents of the CString pointed to by a_pszValue remains unchanged.

 

    

Messages

None

 

    

Usage

The following snippet of code illustrates how to use the GetRexxVariable() function.

 

...

 

CString szName = “MYVARIABLE”;

CString szValue;

 

// Is the variable currently defined.

dwRetCode = m_pManager->GetRexxVariable( ( LPCTSTR )szName, &szValue );

if( dwRetCode == _RC_REXX_SUCCESS_ )

{

    ...

}

else

return( false );

 

...

 

 

bool CStageManager::GetRexxStem(
    _in                          const char *a_pszName,
    _inout                       std::list< CString > *a_plStem );
 

 

     

Purpose

Use GetRexxStem() to obtain the contents of the ooRexx stem, specified by; a_pszName.

 

You must specify the name of the stem, with each index in that name separated by a period (.), for example mystem.i.j. The function will insert the contents of each index in the stem into the corresponding index of the std::list pointed to by a_plStem.

 

    

Parameters

 

 

a_pszName

[in] A constant character pointer to the name of the ooRexx stem.

 

a_plStem

[inout] A pointer to the target std::list.

 

    

Returns

 

 

bool

true if the specified stem is defined, otherwise; false which indicates that the stem is not defined.

 

    

Messages

None

 

    

Usage

The following snippet of code illustrates how to use the GetRexxStem() function.

 

// Access the manager.
m_pManager = Manager();
// Access my stage.
m_pStage = m_pManager->GetStage( *this );

 

...

 

CString szName = “MYSTEM”;

std::list< CString > lStem;

 

 

// If the stem is defined; load the std::list lStem with the contents.

If( m_pManager->GetRexxStem( ( LPCTSTR )szName, &lStem ) )

{

    ...

}

else

{

    // Otherwise; do something else.

    ...

}

 

...

 

 

bool CStageManage::GetRexxArray(

    _in                          const char *a_pszName,

    _out                         std::list< CString > *a_plArray );

 

 

    

Purpose

 

Use GetRexxArray() to obtain the contents of the ooRexx array, specified by; a_pszName.

 

You must specify the name of the array, with each index in that name enclosed in brackets([]), for example myarray[i][j]. The function will insert the contents of each index in the array into the corresponding index of the std::list pointed to by a_plArray.

 

    

Parameters

 

 

a_pszName

[in] A constant character pointer to the name of the ooRexx array.

 

a_plStem

[inout] A pointer to the target std::list.

 

    

Returns

 

 

bool

true if the specified array is defined, otherwise; false which indicates that the array is not defined.

 

    

Messages

None

 

    

Usage

The following snippet of code illustrates how to use the GetRexxArray() function.

 

// Access the manager.
m_pManager = Manager();
// Access my stage.
m_pStage = m_pManager->GetStage( *this );

 

...

 

CString szName = “MYARRAY”;

std::list< CString > lArray;

 

 

// If the array is defined; load the std::list lArray with the contents.

If( m_pManager->GetRexxArray( ( LPCTSTR )szName, &lArray ) )

{

    ...

}

else

{

    // Otherwise; do something else.

    ...

}

 

...

 

 

DWORD CStageManager::GetRexxStemEntry(

    _in                                const char *a_pszName,

    _in                                DWORD a_dwIndex,

    _inout                             CString *a_pszValue );

 

 

    

Purpose

Use GetRexxStemEntry() to access the contents of a stem index, specified by the DWORD a_dwIndex.

 

You must specify the name of the stem, with each index in that name separated by a period (.), for example mystem.i.j. The function will insert the contents of the specified index into the CString pointed to by a_pszValue.

 

    

Parameters

 

 

a_pszName

[in] A constant character pointer to the name of the ooRexx stem.

 

a_dwIndex

[in] The index number of the element that you want to access.

 

a_pszValue

[inout] A pointer to a CString object that will be filled with the contents of the specified stem index.

 

    

Returns

 

 

DWORD

_RC_REXX_SUCCESS_ if the stem index is defined, in which case; the CString pointed to by a_pszValue is filled with the contents of the specified ooRexx stem index, otherwise, the function returns _RC_REXX_INDEX_OUT_OF_RANGE_ where a_dwIndex exceeds the number of elements in the stem and _RC_REXX_ENTRY_NOT_FOUND_ when the ooRexx stem is not currently defined.

 

    

Messages

None

 

    

Usage

The following snippet of code illustrates how to use the GetRexxStemEntry() function.

 

// Access the manager.
m_pManager = Manager();
// Access my stage.
m_pStage = m_pManager->GetStage( *this );

 

...

 

CString szStemName = “MYSTEM”;

DWORD dwIndex = 10;

CString szValue;

 

// Access element number 10.

dwRetCode = m_pManager->GetRexxStemEntry( ( LPCTSTR )szStemName, dwIndex, &m_szValue );

if( dwRetCode == _RC_REXX_SUCCESS_ )

{

     // OK - we have found the rexx stem index entry. So, do something with it..

    ...

 

}

else

{

    // Otherwise; do something else.

    ...

}

 

...

 

 

DWORD CStageManager::GetRexxArrayEntry(
    _in                                 const char *a_pszName,
    _in                                 DWORD a_dwIndex,
    _out                                CString *a_pszValue );
 

 

    

Purpose

Use GetRexxArrayEntry() to access the contents of an array index, specified by the DWORD a_dwIndex.

 

You must specify the name of the array, with each index in that name enclosed in brackets([]), for example myarray[i][j]. The function will insert the contents of the specified index into the CString pointed to by a_pszValue.

 

    

Parameters

 

 

a_pszName

[in] A constant character pointer to the name of the ooRexx array.

 

a_dwIndex

[in] The index number of the element that you want to access.

 

a_pszValue

[inout] A pointer to a CString object that will be filled with the contents of the specified array index.

 

    

Returns

 

 

DWORD

_RC_REXX_SUCCESS_ if the array index is defined, in which case; the CString pointed to by a_pszValue is filled with the contents of the specified ooRexx array index, otherwise, the function returns _RC_REXX_INDEX_OUT_OF_RANGE_ where a_dwIndex exceeds the number of elements in the array and _RC_REXX_ENTRY_NOT_FOUND_ when the ooRexx array is not currently defined.

 

    

Messages

None

 

    

Usage

The following snippet of code illustrates how to use the GetRexxArrayEntry() function.

 

// Access the manager.
m_pManager = Manager();
// Access my stage.
m_pStage = m_pManager->GetStage( *this );

 

...

 

CString szArrayName = “MYARRAY”;

DWORD dwIndex = 10;

CString szValue;

 

// Access element number 10.

dwRetCode = m_pManager->GetRexxArrayEntry( ( LPCTSTR )szArrayName, dwIndex, &m_szValue );

if( dwRetCode == _RC_REXX_SUCCESS_ )

{

     // OK - we have found the rexx array index entry. So, do something with it..

    ...

 

}

else

{

    // Otherwise; do something else.

    ...

}

 

...

 

 

DWORD CStageManager::GetRexxStemSize(

    _in                               const char *a_pszName );

 

 

    

Purpose

Use GetRexxStemSize() to determine the number of entries in the stem specified by the constant character pointer a_pszName .

 

    

Parameters

 

 

[in] A constant character pointer to an ooRexx stem name.

 

    

Returns

 

 

DWORD

The number of entries in the stem.

 

    

Messages

None

 

    

Usage

The following example shows a how you might use GetRexxStemSize() to determine the number of entries in a stem name specified on your stage command argument.

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    ...
 

    CString szName;

 

    // Access my argument.

    const char *pszArgument = m_pStage->Argument();
 

    m_pToken->m_pszSource = &pszArgument;

    m_pToken->m_pszTarget = &szName;

 

    // Extract the array name.

    m_pManager->ParseForToken( m_pToken );

 

    // Store the size of the stem for use later in our Go() function.

    m_dwArraySize = m_pManager->GetRexxStemSize( ( LPCTSTR )szName );

 

    ...

 

    return( true )

}

 

 

DWORD CStageManager::GetRexxArraySize(
    _in                                const char *a_pszName );
 

 

    

Purpose

Use GetRexxArraySize() to determine the number of entries in the array specified by the constant character pointer a_pszName .

 

    

Parameters

 

 

const char *a_pszName

[in] A constant character pointer to an ooRexx array name.

 

    

Returns

 

 

DWORD

The number of entries in the array.

 

    

Messages

None

 

    

Usage

The following example shows a how you might use GetRexxArraySize() to determine the number of entries in an array name specified on your stage command argument.

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    ...
 

    CString szName;

 

    // Access my argument.

    const char *pszArgument = m_pStage->Argument();
 

    m_pToken->m_pszSource = &pszArgument;

    m_pToken->m_pszTarget = &szName;

 

    // Extract the array name.

    m_pManager->ParseForToken( m_pToken );

 

    // Store the size of the array for use later in our Go() function.

    m_dwArraySize = m_pManager->GetRexxArraySize( ( LPCTSTR )szName );

 

    ...

 

    return( true )

}

 

 

bool CStageManager::IsRexxVariable(

    _in                             const char *a_pszName,

    _in                             DWORD a_dwType );

 

 

    

Purpose

Use IsRexxVariable() to determine if the specified name defined by the constant character pointer a_pszName is a currently defined ooRexx variable.

 

    

Parameters

 

 

const char *a_pszName

[in] A constant character pointer to an ooRexx variable name.

 

    

Returns

 

 

bool

true if the variable is defined, otherwise; false which indicates that the variable is not defined.

 

    

Messages

None

 

    

Usage

The following example shows a simple example of how to use the IsRexxVariable() function to determine if the contents of the CString m_szName is a currently defined ooRexx variable.

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    ...
 

    // If it's a variable ...

    if( m_pManager->IsRexxVariable( ( LPCTSTR )m_szName ) )

    {

        ...

 

        return( false );

    }
 
    ...
 
    return( true );

}

 

 

bool CStageManager::IsRexxStem(

    _in                         const char *a_pszName );

 

 

    

Purpose

Use IsRexxStem() to determine if the specified name defined by the constant character pointer a_pszName is a currently defined ooRexx stem.

 

    

Parameters

 

 

const char *a_pszName

[in] A constant character pointer to an ooRexx stem name.

 

    

Returns

 

 

bool

true if the stem is defined, otherwise; false which indicates that the stem is not defined.

 

    

Messages

None

 

    

Usage

The following example shows a simple example of how to use the IsRexxStem() function to determine if the contents of the CString m_szName is a currently defined ooRexx stem.

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    ...
 

    // If it's a stem ...

    if( m_pManager->IsRexxStem( ( LPCTSTR )m_szName ) )

    {

        ...

 

        return( false );

    }
 
    ...
 
    return( true );

}

 

 

bool CStageManager::IsRexxArray(

    _in                          const char *a_pszName );

 

 

    

Purpose

Use IsRexxArray() to determine if the specified name defined by the constant character pointer a_pszName is a currently defined ooRexx array.

 

    

Parameters

 

 

const char *a_pszName

[in] A constant character pointer to an ooRexx array name.

 

    

Returns

 

 

bool

true if the array is defined, otherwise; false which indicates that the array is not defined.

 

    

Messages

None

 

    

Usage

The following example shows a simple example of how to use the IsRexxArray() function to determine if the contents of the CString m_szName is a currently defined ooRexx array.

 

bool CMyStage::Initialise( void )
{
    // Access the manager.
    m_pManager = Manager();
    // Access my stage.
    m_pStage = m_pManager->GetStage( *this );
 
    ...
 

    // If it's an array ...

    if( m_pManager->IsRexxArray( ( LPCTSTR )m_szName ) )

    {

        ...

 

        return( false );

    }
 
    ...
 
    return( true );

}

 

 

CRexxEntry *CStageManager::AddRexxEntry( void );
 

 

    

Purpose

Use AddRexxEntry() to add a Rexx variable, stem or array update to the set of entries currently defined in the session Directory Object.

 

ooRexx will only allow the update of a variable, stem or array within its own execution thread. Your Pipelines Stage DLL will execute in a separate thread, and so, anything that you create, modify or destroy will only get finalised after Pipelines has terminated. The AddRexxEntry() function will create a new CRexxEntry object, adding it to a list of updates to be actioned and return a pointer to it; so that you can fill in the detail. This ‘TODO’ list will get processed by Pipelines automatically at the close of play, so, any updates that you have added will be processed just before Pipelines returns to its caller – ooRexx.

 

    

Parameters

 

 

void

    

Returns

 

 

bool

true if the array is defined, otherwise; false which indicates that the array is not defined.

 

    

Messages

None

 

    

Usage

The following example shows the SRexxVariable structure and an edited excerpt from the CVar stage class commands’ Go() function. The portion of code shown; illustrates how the AddRexxEntry() function is used to create a new ooRexx variable.

 

enum m_eRexxVariableAction { m_eUndefined, m_eUpdate, m_eDrop, m_eAppend };

enum m_eRexxVariableType { m_eVariable, m_eStem, m_eArray };

 

struct SRexxVariable

{

    std::list< CString > m_lStem;

    CString m_szName;

    CString m_szValue;

    DWORD m_dwAction;

};

 

DWORD CVar::Go( void )

{

    ...

 

    CString szRecord;

 

    // Create the new rexx entry object.

    CRexxEntry *pRexxEntry = m_pManager->AddRexxEntry();

    pRexxEntry->Type( CRexxEntry::m_eVariable );

    // Set the initial action for update.

    pRexxEntry->Action( CRexxEntry::m_eUpdate );

    pRexxEntry->Name( m_szName );

    pRexxEntry->Value( “” );

 

    // Ok, now lets read and process the primary input stream.

    for( ;; )

    {

        // Read a record from the primary input stream.

        if( !m_pManager->PeekRecord( *this, 0, &szRecord ) )

            break;

 

        ...

 

        // Store the variable value in the rexx entry structure.

        pRexxEntry->Value( szRecord );

 

        // Write the record to primary output stream.

        if( !m_pManager->WriteRecord( *this, 0, &szRecord ) )

            break;

 

        // Release the stage that we read from.

        m_pManager->ConsumeRecord( *this, 0 );

    }

 

    ...

 

    return( _RC_SUCCESS_ );

}