Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Example 7 - Multiple Matches

Introduction

This example demonstrates searching for multiple matches within a search text (similar to the functionality provided by Perl's "/g&quotl modifier. This example matches each line in the text and prints the result of each search.

Demonstrates

This example demonstrates the following RGX features:

  • Loading and invoking the p6IRegex component interface.
  • The use the P6MODIFIER_MULTILINE modifier.
  • Using the offset and length to increment the search position.
  • Use of the getCaptureText() method.

Also see the CConsoleStream example for and example of creating the optional debug p6IDataStream which is passed into p6loader.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory> // nothrow
#include "p6rgx.h"
#include "cconsolestream.h"
using namespace P6R;
P6DECLARE_CID( p6Regex);
namespace {
//
// The example text to search.
//
static const P6CHAR gszSearch[] = "one\ntwo\nthree\nfour\nfive";
P6R::P6ERR runRegex( p6IDataStream *pStreamDebug )
{
P6ERR err = eOk;
//
// Create and instance of the regex component
// and initialize it, telling it that we want
// to use PERL style regular expressions.
//
// The VALIDATECOMPTR() macro is used to provide
// compile time type safety, by preventing the
// assignment of an interface to the wrong pointer
// (or smartptr in this case) type.
//
if(P6SUCCEEDED(err = p6CreateInstance(NULL,CID_p6Regex,VALIDATECOMPTR(p6IRegex,cpRegex)))) {
//
// Compile our regular expression
//
// For this simple example, we will just be
// searching for complete lines of text.
//
// ^ - matches the beginning of a line
// ([a-zA-Z0-9_., \\t]+) - is a defines the set of characters
// that we want to match. The '+'
// indicates the we should match one
// or more characters in the set.
// finally the enclosing parens '()'
// define the text that will be
// captured. This text is retrieved
// using the getCaptureText() method.
// [\\n\\r]* Finally we match the line separator
// characters. '*' indicates matching
// zero or more, and this allows us to
// match the last line which does not
// have a newline at the end. It's
// important to note that the matchLength
// returned by search will include the
// new line characters, allowing use
// to skip past them when searching for
// the next match.
//
if(P6SUCCEEDED(err = cpRegex->compile("^([a-zA-Z0-9_., \\t]+)[\\n\\r]*",P6MODIFIER_NULL))) {
P6UINT32 i=0;
P6UINT32 matchOffset = 0;
P6UINT32 matchLength = 0;
do {
cpRegex->search(&gszSearch[i],P6MODIFIER_MULTILINE,&matchOffset,&matchLength);
if(matchLength) {
P6UINT32 capLength = 0;
P6UINT32 capOffset = 0;
P6CHAR szBuf[512];
P6BSTR bStr;
P6ARG args[3];
//
// Use getCaptureText() to get the offset and
// length of our captured text.
//
cpRegex->getCaptureText(1,&capOffset,&capLength);
//
// Put the capture information in a P6BSTR
// and render it using the handy p6ISafeString::formatString()
// method. P6BSTR is length delimited string (a pointer and length)
// like a Pascal string and is perfect for the offset/length
// information returned by the RGX API.
//
bStr.pString = (P6UCHAR*)&gszSearch[i+capOffset];
bStr.length = capLength;
P6AI_UINT32(&args[0],i+matchOffset); // Macro to initialize a P6ARG with a UINT32
P6AI_UINT32(&args[1],matchLength); // Macro to initialize a P6ARG with a UINT32
P6AI_BSTR(&args[2],&bStr); // Macro to initialize a P6ARG with a P6BSTR
//
// formatString() can render most all of the P6R types
// (eg. P6UINT32, P6BSTR, P6TIME, P6WCHAR). It ALWAYS
// NULL terminates the output, uses position independent
// notation to make I18n and L10n easier, and has many
// safety mechanisms to prevent overruns.
//
cpStr->formatString(&szBuf[0],P6CHARCNT(szBuf),NULL,"Match: %1$:%2$ [ %3$ ]\n",&args[0],3);
printf(&szBuf[0]);
//
// Make sure to use the information returned from the
// search() method (and not getCaptureText()) to
// increment the position in the search text for the
// next search.
//
i += matchOffset+matchLength;
}
} while(matchLength != 0); // <- A match length of zero indicates no match found
}
}
}
}
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;
}