Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Example 3 - Narrow Examples Including Split and Explode

Simple examples illustrating counting, capture, split and explode

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory> // nothrow
#include "p6rgx.h"
using namespace P6R;
P6DECLARE_CID( p6Regex );
P6DECLARE_CID( p6Split );
namespace {
//
// Simple p6IDataStream implementation which outputs
// data to stdout (via printf). This implementation
// is not thread-safe, but is adequate for this
// example.
//
class CConsoleStream : public P6R::p6IDataStream
{
public:
//
// Standard [p6]COM queryInterface() method.
//
P6COMMETHOD queryInterface( const P6R::IID &iid, P6R::P6VOID **ppIface )
{
if (!ppIface) return eAccessFault;
*ppIface = NULL;
if(iid == IID_p6ICom) *ppIface = static_cast<p6IDataStream*>(this);
else if(iid == IID_p6IDataStream) *ppIface = static_cast<p6IDataStream*>(this);
else return eNoInterface;
reinterpret_cast<p6ICom*>(*ppIface)->addref();
return eOk;
}
//
// Standard [p6]COM addref() method.
//
{
return m_cRef++;
}
//
// Standard [p6]COM release() method.
//
{
P6INT32 tmp = 0;
if(0 == (tmp = (--m_cRef))) { delete this; }
return tmp;
}
//
// beginStream() method prepares the stream for use.
//
P6COMMETHOD beginStream()
{
return eOk;
}
//
// processStream() is call to pass data to the data stream.
// This method then performs it's stream specific
// operations on the data (in this case, writing it out
// to stdout).
//
// Since printf() requires an ASCIIZ string (NULL terminated string),
// this method first copies the data into a buffer and NULL
// terminates, then passes that to printf().
//
P6COMMETHOD processStream( const P6R::P6VOID* pData, P6R::P6UINT32 cData )
{
//
// Free the buffer if we do not have enough room
//
if (m_cBuffer && cData+1 > m_cBuffer)
{
free( m_pBuffer );
m_pBuffer = NULL;
m_cBuffer = 0;
}
//
// Allocate the buffer if not already allocated
//
if (!m_pBuffer)
{
m_pBuffer = (P6CHAR*) malloc(cData+1);
m_cBuffer = cData;
}
//
// Output the data to the console
//
if (m_pBuffer)
{
memcpy( m_pBuffer, pData, cData );
m_pBuffer[cData] = '\0';
printf( m_pBuffer );
}
return eOk;
}
//
// endStream() is called to notify the stream that there is
// no more data to be processed. In this simple case there is
// nothing to do.
//
P6COMMETHOD endStream() { return eOk; }
//
// This method creates a new uninitialized instance
// of our component and returns a pointer to the
// requested interface.
//
static P6R::P6ERR createInstance( P6R::p6ICom *pOuter, const P6R::IID &iid, P6R::P6VOID **ppIface )
{
P6ERR err = eNoMemory;
CConsoleStream *pObj = NULL;
if(NULL != pOuter) return eNoAgregation;
if(NULL == ppIface) return eAccessFault;
*ppIface = NULL;
if (NULL != (pObj = new (std::nothrow) CConsoleStream() ))
{
pObj->addref();
err = pObj->queryInterface( iid, ppIface );
pObj->release();
}
return err;
}
CConsoleStream() : m_cRef(0), m_pBuffer(NULL), m_cBuffer(0) {;}
virtual ~CConsoleStream() { if (m_pBuffer) free(m_pBuffer); }
protected:
P6INT32 m_cRef; // Holds the components reference count
P6CHAR *m_pBuffer; // A pointer to our output buffer.
P6UINT32 m_cBuffer; // The current size in characters of our output buffer
};
P6R::P6ERR runRegex( p6IDataStream *pStreamDebug )
{
P6CHAR szErr[64];
P6UINT32 offset = 0;
P6UINT32 strLength = 0;
P6ERR err = eOk;
// Here we are using the narrow string regex library to do the same set of operations as we did in regex example 1
if (P6FAILED( err = p6CreateInstance( NULL, CID_p6Regex, VALIDATECOMPTR( p6IRegex, cpRegex )))) return err;
if (P6FAILED( err = cpRegex->initialize( P6REGEX_NOFLAGS, P6REGEX_PERL ))) return err;
if (P6FAILED( err = p6CreateInstance( NULL, CID_p6Split, VALIDATECOMPTR( p6ISplit, cpSplit )))) return err;
if (P6FAILED( err = cpSplit->initialize( P6SPLIT_NOFLAGS ))) return err;
// [A] Counting
err = cpRegex->compile( "(abc){3,7}", P6MODIFIER_NULL );
if (P6FAILED( err )) printf( "1 - Compile 1 failed %x\n", err );
offset = 0;
strLength = 0;
if (P6SUCCEEDED( err = cpRegex->search( "confabcabcabc-9393939", P6MODIFIER_FASTGREEDY, &offset, &strLength )))
{
if (4 != offset || 9 != strLength) printf( "2 - Expected 4,9 but got %d,%d\n", offset, strLength );
}
// -> (abc) will capture text
offset = 0;
strLength = 0;
if (P6SUCCEEDED( err = cpRegex->getCaptureText( 1, &offset, &strLength )))
{
if (4 != offset || 9 != strLength) printf( "3 - Expected 4,9 but got %d,%d\n", offset, strLength );
}
// [B] Use split which returns an enumerator of the returned chunks split by the given regex
P6SPLITCHUNK chunk;
P6UINT32 numReturned = 0;
P6UINT32 count = 0;
err = cpSplit->split( "(<[^>]*>)", P6MODIFIER_NULL, "and <B>very <FONT color=red>very</Font> much</B> effort", 0, cpEnum.addressofWithRelease() );
if (P6FAILED( err )) printf( "4 - Compile 2 failed %x\n", err );
// -> the enumerator returned is like all P6R returned enumerators
while( P6SUCCEEDED( err ))
{
chunk.offset = 0;
chunk.length = 0;
err = cpEnum->next( 1, &chunk, &numReturned );
if (eEndOfFile == err || 0 == numReturned) break;
switch( count ) {
case 0: if (0 != chunk.offset || 4 != chunk.length) printf( "5 - Expected 0,4 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 1: if (4 != chunk.offset || 3 != chunk.length) printf( "6 - Expected 4,3 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 2: if (7 != chunk.offset || 5 != chunk.length) printf( "7 - Expected 7,5 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 3: if (12 != chunk.offset || 16 != chunk.length) printf( "8 - Expected 12,16 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 4: if (28 != chunk.offset || 4 != chunk.length) printf( "9 - Expected 28,4 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 5: if (32 != chunk.offset || 7 != chunk.length) printf( "10 - Expected 32,7 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 6: if (39 != chunk.offset || 5 != chunk.length) printf( "11 - Expected 39,5 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 7: if (44 != chunk.offset || 4 != chunk.length) printf( "12 - Expected 44,4 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 8: if (48 != chunk.offset || 7 != chunk.length) printf( "13 - Expected 48,7 but got %d,%d\n", chunk.offset, chunk.length ); break;
}
numReturned = 0;
count++;
}
// [C] Explode is a simple form of split where a character string (instead of a regex) is given as a string divide.
// -> Split can always be used to do exactly what explode does
count = 0;
err = cpSplit->explode( "*******", "part 1******* part 2 ******* part 3 ******* part 4", 0, cpEnum.addressofWithRelease() );
if (P6FAILED( err )) printf( "14 - Compile 3 failed %x\n", err );
while( P6SUCCEEDED( err ))
{
chunk.offset = 0;
chunk.length = 0;
err = cpEnum->next( 1, &chunk, &numReturned );
if (eEndOfFile == err || 0 == numReturned) break;
switch( count ) {
case 0: if (0 != chunk.offset || 6 != chunk.length) printf( "15 - Expected 0,6 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 1: if (13 != chunk.offset || 10 != chunk.length) printf( "16 - Expected 13,10 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 2: if (30 != chunk.offset || 9 != chunk.length) printf( "17 - Expected 30,9 but got %d,%d\n", chunk.offset, chunk.length ); break;
case 3: if (46 != chunk.offset || 7 != chunk.length) printf( "18 - Expected 46,7 but got %d,%d\n", chunk.offset, chunk.length ); break;
}
numReturned = 0;
count++;
}
if (eEndOfFile == err) err = eOk;
if (P6FAILED( err )) printf("example failed due to [ %s ]\n", p6ErrToStr(err,&szErr[0],P6CHARCNT(szErr)));
return err;
}
} // namespace
int main(int argc,char *argv[])
{
P6ERR err = eOk;
P6CHAR szTmp[32];
if ( P6SUCCEEDED( err = CConsoleStream::createInstance( NULL, VALIDATECOMPTR( p6IDataStream, cpDataStream ))))
{
if ( P6SUCCEEDED( err = p6InitializeLoader( cpDataStream, 9, P6SCLF_NOFLAGS )))
{
err = runRegex( cpDataStream );
printf( "runRegex result: [ %s ]\n", p6ErrToStr(err, &szTmp[0], P6CHARCNT(szTmp)) );
}
else printf("ERROR: Failed to initialize the loader [ %x ]\n", err );
}
else printf( "ERROR: Failed to create CConsoleStream [ %x ]\n", err );
return err;
}