Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cxpathextend.cpp
#include "cxpathextend.h"
using namespace P6R;
// -> we have lots of strings to compare, put them all in a table instead of code
struct stringTable
{
const P6R::P6WCHAR* pName;
P6R::P6UINT32 nameLength;
const P6R::P6WCHAR* pValue;
P6R::P6UINT32 valueLength;
P6R::P6UINT32 numValue;
};
typedef stringTable lookTable_t;
// -> put the strings in a constant table rather than in code
// -> XSLT extension functions we recognize
//
// -> ** NOTE **, the second entry is a QName, see XSLT documentation on how we encode QNames
const P6UINT32 NUM_FUNCTIONS = 4;
const lookTable_t availableFunctions[ NUM_FUNCTIONS ] =
{
{ P6CTEXT("getclickurl"), 11, P6CTEXT(""), 0, 1 },
{ P6CTEXT("http-&&www.p6r.com&namespaces&test&p-setclick88"), 47, P6CTEXT(""), 0, 2 },
{ P6CTEXT("abc"), 3, P6CTEXT(""), 0, 3 },
};
//
CXpathExtend::CXpathExtend() : m_cRef( 1 ),
m_bInitialized( P6FALSE ),
m_pStr( NULL )
{}
CXpathExtend::~CXpathExtend()
{
if (NULL != m_pStr) m_pStr->release();
}
P6COMMETHODIMPL CXpathExtend::queryInterface( const P6R::IID &iid, P6R::P6VOID **ppIface )
{
if (!ppIface) return eAccessFault;
*ppIface = NULL;
if (iid == IID_p6ICom ) *ppIface = static_cast<p6ICom*>(this);
else if (iid == IID_p6IXpathVariables) *ppIface = static_cast<p6IXpathVariables*>(this);
else return eNoInterface;
reinterpret_cast<p6ICom*>(*ppIface)->addref();
return eOk;
}
//
P6R::P6ERR CXpathExtend::initialize( p6ISafeString* pStr )
{
if (m_bInitialized) return eAlreadyInitialized;
if (NULL == pStr ) return eInvalidArg;
m_pStr = pStr;
m_pStr->addref();
m_bInitialized = P6TRUE;
return eOk;
}
// Look up variables that contain any of the standard P6XPATH_VAR types.
//
P6COMMETHODIMPL CXpathExtend::lookupVariable( P6WCHAR* pVarName, P6XPATH_VAR* pVarValue )
{
P6INT32 match = -1;
P6ERR err = eNotFound;
// -> call m_pEvalContext to a method to look up varname
if (NULL == pVarName || NULL == pVarValue) return eInvalidArg;
m_pStr->setMem( pVarValue, 0, sizeof( P6XPATH_VAR ));
err = m_pStr->wstrncmp( pVarName, (const P6WCHAR*)P6TEXT("$externalVar1"), 13, &match );
if (P6SUCCEEDED( err ) && 0 == match)
{
pVarValue->iResult = 55;
pVarValue->type = P6XPATH_TYPE_INT;
return eOk;
}
err = m_pStr->wstrncmp( pVarName, (const P6WCHAR*)P6TEXT("$externalVar2"), 13, &match );
if (P6SUCCEEDED( err ) && 0 == match)
{
pVarValue->pString = P6TEXT("External data from application");
pVarValue->strLength = 30;
pVarValue->type = P6XPATH_TYPE_STR;
return eOk;
}
// -> lets us easily compose a wide string
err = m_pStr->wstrncmp( pVarName, (const P6WCHAR*)P6TEXT("$external55"), 11, &match );
if (P6SUCCEEDED( err ) && 0 == match)
{
pVarValue->pString = P6TEXT("espac\x00E9"); // latin small letter E with Acute
pVarValue->strLength = 6;
pVarValue->type = P6XPATH_TYPE_STR;
return eOk;
}
err = m_pStr->wstrncmp( pVarName, (const P6WCHAR*)P6TEXT("$collate1"), 9, &match );
if (P6SUCCEEDED( err ) && 0 == match)
{
// -> XSLT applications already deal with differences in collation strings, this is how they can do it
#if defined( P6_WINDOWS )
pVarValue->pString = P6TEXT("French_France.1252"); // windows collation string
pVarValue->strLength = 18;
#elif defined( P6_LINUX )
pVarValue->pString = P6TEXT("fr_FR.utf8"); // linux collation string
pVarValue->strLength = 10;
#elif defined( P6_SOLARIS )
pVarValue->pString = P6TEXT("fr_FR.utf8"); // what is used on solaris?
pVarValue->strLength = 10;
#endif
pVarValue->type = P6XPATH_TYPE_STR;
return eOk;
}
return err;
}
// Entry point from XPath
//
P6COMMETHODIMPL CXpathExtend::externFunction( P6WCHAR* pFuncName,
P6UINT32 funcLength,
P6XPATH_RESULT* pParams, // IN: an array of parameters
P6UINT32 numParams, // IN: size of the pParams array
P6XPATH_VAR* pVarValue
)
{
P6WCHAR buffer[2000];
p6IDOMNodeset* pSet = NULL;
p6IXMLNode* pChild = NULL;
P6INT32 match = -1;
P6UINT32 count = 0;
P6UINT32 length = 0;
P6UINT32 code = 0;
P6ERR err = eOk;
P6ERR err1 = eOk;
if (NULL == pFuncName || NULL == pVarValue) return eInvalidArg;
err = matchFunction( pFuncName, &code );
if (P6FAILED( err ) && eNotFound != err) return err;
m_pStr->setMem( pVarValue, 0, sizeof( P6XPATH_VAR ));
m_pStr->setMem( &temp, 0, sizeof( P6XPATH_RESULT ));
//printf( "\napp ext [%ls] %d\n", pFuncName, funcLength );
switch( code ) {
case 1: // getclickurl
pVarValue->bResult = P6TRUE;
pVarValue->type = P6XPATH_TYPE_BOOL;
break;
case 2: // setclickurl() -- verify parameter passed as value
if (1 < numParams)
{
pSet = pParams[1].pNodeSet;
pSet->reset();
while( P6SUCCEEDED( err1 = pSet->next( &pChild )))
{
length = 2000;
err = pChild->toString( buffer, &length );
pChild->release();
switch( count ) {
case 0:
err = m_pStr->wstrncmp( P6TEXT("Item 1"), buffer, 6, &match );
if (P6FAILED( err ) || 0 != match)
{
pVarValue->type = P6XPATH_TYPE_NULL;
return eOk;
}
break;
case 1:
err = m_pStr->wstrncmp( P6TEXT("Item 2"), buffer, 6, &match );
if (P6FAILED( err ) || 0 != match)
{
pVarValue->type = P6XPATH_TYPE_NULL;
return eOk;
}
break;
case 2:
err = m_pStr->wstrncmp( P6TEXT("Item 3"), buffer, 6, &match );
if (P6FAILED( err ) || 0 != match)
{
pVarValue->type = P6XPATH_TYPE_NULL;
return eOk;
}
break;
}
count++;
}
}
// -> need some result
pVarValue->bResult = P6TRUE;
pVarValue->type = P6XPATH_TYPE_BOOL;
break;
case 3: // abc()
// verify parameter passed value
pVarValue->bResult = P6TRUE;
pVarValue->type = P6XPATH_TYPE_BOOL;
break;
default:
err = eNotFound;
break;
}
return err;
}
//
P6R::P6ERR CXpathExtend::matchFunction( P6WCHAR* pFunctionName, P6UINT32* pFunctionCode )
{
P6INT32 match = 0;
P6ERR err = eOk;
*pFunctionCode = 0;
for( P6UINT8 i=0; i < NUM_FUNCTIONS; i++ )
{
err = m_pStr->wstrnicmp( availableFunctions[i].pName, pFunctionName, availableFunctions[i].nameLength, &match );
if (P6SUCCEEDED( err ) && 0 == match)
{
*pFunctionCode = availableFunctions[i].numValue;
return eOk;
}
}
return eNotFound;
}