📄 tmapr.cpp
字号:
Cleanup:
ASSERT(SUCCEEDED(hr));
return (hr);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: HRESULT CCDATAMapper::write(ISoapSerializer* pSoapSerializer, BSTR bstrEncoding, enEncodingStyle enStyle, long lFlags, VARIANT * pvar)
//
// parameters:
//
// description:
// mapping a string into a soap message
//
// returns:
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CCDATAMapper::write(ISoapSerializer* pSoapSerializer, BSTR bstrEncoding, enEncodingStyle enStyle, long lFlags, VARIANT * pvar)
{
HRESULT hr=S_OK;
CVariant varChanged;
CHK (ConvertData(*pvar, (VARIANT *)&varChanged, VT_BSTR));
CHK (pSoapSerializer->writeXML((BSTR)g_pwstrOpenCDATA));
CHK (pSoapSerializer->writeXML(V_BSTR(&varChanged)));
CHK (pSoapSerializer->writeXML((BSTR)g_pwstrCloseCDATA));
Cleanup:
ASSERT(SUCCEEDED(hr));
return (hr);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: WCHAR * CSafearrayMapper::skipNoise(WCHAR * pc)
//
// parameters:
//
// description:
// simple function to skip over blank and tab character
//
// returns:
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
WCHAR * CSafearrayMapper::skipNoise(WCHAR * pc)
{
while (pc && *pc)
{
if ( (*pc == '\t') || (*pc == ' '))
pc++;
else
break;
}
return (pc);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: HRESULT CSafearrayMapper::ParseArrayDimensions(WCHAR * pcDefDim, long * pDimCount, long ** ppDim)
//
// parameters:
//
// description:
// function parses string of the form "#,#,#,#]"
// values for # are returned in an array of long (ppDim), count of # in pDimCount
// any error case returns non-S_OK HRESULT
//
// returns:
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CSafearrayMapper::ParseArrayDimensions(WCHAR * pcDefDim, long * pDimCount, long ** ppDim)
{
HRESULT hr=S_OK;
CAutoP<long> pDims(NULL); // a temporary array to keep track of things
long lDim = 0; // use this to count
ASSERT (pcDefDim);
ASSERT (pDimCount);
ASSERT (ppDim);
CHK_BOOL(pcDefDim && *pcDefDim, E_INVALIDARG);
while (1)
{
{
CAutoP<long> pl(NULL); // need this for temporary copy area
// we are ready to read a new dimenion, create an array
// with sufficient room for it
pl = (long*) new BYTE[sizeof(long) * (lDim+1)];
CHK_BOOL(pl, E_OUTOFMEMORY);
// move the current contents into this one if necessary
if (pDims)
memcpy(pl, pDims, sizeof(long) * lDim);
// and take ownership of the new one
pDims.Clear();
pDims = pl.PvReturn();
}
long ltemp;
WCHAR *pcTemp;
pcDefDim = skipNoise(pcDefDim);
CHK_BOOL(pcDefDim && *pcDefDim, E_INVALIDARG);
if ( (*pcDefDim == ',') || (*pcDefDim == ']') )
{
// this is the case where we have no number, this dimension is going to be unbounded
ltemp = -1;
pcTemp = pcDefDim;
}
else
{
// there better be a number around ... let's figure it out
ltemp = wcstol(pcDefDim, &pcTemp, 10);
}
CHK_BOOL((ltemp != LONG_MAX) && (ltemp != LONG_MIN) && (pcTemp!=NULL) && (*pcTemp != 0), E_INVALIDARG);
pcTemp = skipNoise(pcTemp);
// throw the value into the array
pDims[lDim] = ltemp;
if (*pcTemp == ',')
{
// we are going to see another dimension ...
lDim ++;
pcDefDim = pcTemp+1;
pcDefDim = skipNoise(pcDefDim);
CHK_BOOL(pcDefDim && *pcDefDim, E_INVALIDARG);
// at this point we are ready to keep reading
}
else
{
if (*pcTemp == ']')
{
// in this case we are done
break;
}
// no clue what got us here, we can handle this - kind of
CHK (E_INVALIDARG);
}
}
// take ownership of what we returned
*ppDim = pDims.PvReturn();
// and remember the number of dimensions
*pDimCount = lDim +1;
Cleanup:
ASSERT(hr == S_OK);
return hr;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: HRESULT CSafearrayMapper::init(ISoapTypeMapperFactory *ptypeFactory, IXMLDOMNode * pSchema, enXSDType xsdType)
//
// parameters:
//
// description:
// set the constrains for this guy
// returns:
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CSafearrayMapper::init(ISoapTypeMapperFactory *ptypeFactory, IXMLDOMNode * pSchema, enXSDType xsdType)
{
HRESULT hr = S_OK;
CAutoRefc<IXMLDOMNode> pArraySchema(NULL);
XPathState xp;
// we should only initialize once
ASSERT (m_ptypeFactory == NULL);
// set the object into an empty state
m_lDimensions = -1;
m_pabound.Clear();
m_bstrElementName.Clear();
m_bstrTypeURI.Clear();
m_bstrTypeName.Clear();
m_LvtType = -1;
m_soaparraydef = FALSE;
m_enRevision = enSchemaInvalid;
// check for needed parameter
CHK_BOOL(ptypeFactory, E_INVALIDARG);
// start initializing
CHK(CTypeMapper::init(ptypeFactory, pSchema, xsdType));
// hold on to the typefactory, we will need this later
assign(&m_ptypeFactory, ptypeFactory);
if (pSchema == NULL)
{
// in this case we are assuming we are getting called
// from inside the AnyType-Mapper and will do standard
// variant type discovery later
m_enXSDType = enXSDanyType;
return S_OK;
}
// from here on we need a schema
CHK_BOOL(pSchema, E_INVALIDARG);
CHK(_XSDFindRevision(pSchema, &m_enRevision));
CHK (xp.init(pSchema));
// set up our prefixes we can use in xpath
CHK (xp.addNamespace(g_pwstrXpathEnc)); //give us enc: for encoding
CHK (xp.addNamespace(g_pwstrXpathDef)); //give us def: wsdl
// we need a schema namespace to look for - actually, we do not care if it is a
// 1999 or 2000
{
CAutoFormat autoFormat;
CHK(autoFormat.sprintf(L"xmlns:schema='%s'", _XSDSchemaNS(m_enRevision)));
CHK (xp.addNamespace(&autoFormat)); //gives us schema:
}
showNode(pSchema);
// again 5 scenarios we want to check for:
// (1) <element><complexType><sequence><element>
// (2) <complexType><sequence><element>
// (3) <element><complexType><element>
// (4) <complexType><complexContent><restriction><attribute>
// (5) <complexType><complexContent><restriction><sequence><attribute>
// lets try to figure out if we are in 1,2,3 or 5
pSchema->selectSingleNode(L".//schema:complexType/schema:sequence/schema:element", &pArraySchema);
if (!pArraySchema)
pSchema->selectSingleNode(L".//schema:sequence/schema:element", &pArraySchema);
if (!pArraySchema)
pSchema->selectSingleNode(L".//schema:complexType/schema:element", &pArraySchema);
if (!pArraySchema)
pSchema->selectSingleNode(L".//schema:complexContent/schema:restriction/schema:sequence/schema:attribute", &pArraySchema);
if (pArraySchema)
{
CAutoBSTR bstrType;
// we are on an element node now in pArraySchema...get the information we need ...
CHK( _XPATHFindAttribute(pArraySchema, g_pwstrName, &m_bstrElementName));
CHK ( _XPATHFindAttribute(pArraySchema, g_pwstrXSDtype, &bstrType) );
CHK_BOOL(bstrType, E_FAIL);
{
WCHAR achPrefix[_MAX_ATTRIBUTE_LEN];
CAutoBSTR bstrtemp;
CHK(_WSDLUtilSplitQName(bstrType, achPrefix, &m_bstrTypeName));
CHK (_XSDFindURIForPrefix(pArraySchema, achPrefix, &m_bstrTypeURI));
//this thing will allways have one dimension
m_pabound = (SAFEARRAYBOUND*)new BYTE[sizeof(SAFEARRAYBOUND)];
CHK_BOOL(m_pabound, E_OUTOFMEMORY);
m_pabound[0].cElements = -1;
m_pabound[0].lLbound = 0;
m_lDimensions = 1;
//find the maxOccurs values
CHK ( _XPATHFindAttribute(pArraySchema, g_pwstrMaxOccurs, &bstrtemp) );
if (bstrtemp)
{
long ltemp = -1;
if ((wcsicmp(bstrtemp, g_pwstrUnbounded)!= 0)&&(wcsicmp(bstrtemp, g_pwstrStar)!= 0))
{ // maxOccurs != "unbounded" and maxOccurs != "*"
WCHAR *ptemp = NULL;
// figure out maxoccurs:
ltemp = wcstol(bstrtemp, &ptemp, 10);
CHK_BOOL((ltemp != LONG_MAX) && (ltemp != LONG_MIN) && (ptemp!=NULL) && (*ptemp == 0) && (ltemp>=0), E_INVALIDARG);
}
m_pabound[0].cElements = ltemp;
}
m_soaparraydef = FALSE;
TRACE ( ("cElemts: %d lLBound: %d type: %S %S\n", m_pabound[0].cElements, m_pabound[0].lLbound, m_bstrTypeName, m_bstrTypeURI) );
}
}
else
{
CAutoBSTR bstrType;
// we better be in scenario 4 ....
pSchema->selectSingleNode(L".//schema:complexContent/schema:restriction/schema:attribute", &pArraySchema);
CHK_BOOL(pArraySchema, E_FAIL); // in case we could not recognize anything
showNode(pArraySchema);
// assume we do soapencoding here always
CHK ( _XPATHFindAttribute(pArraySchema, _T("def:arrayType"), &bstrType) );
CHK_BOOL(bstrType, E_FAIL);
// check if it is an arraytype
WCHAR * pDimension = wcsstr(bstrType, L"[");
CHK_BOOL(pDimension, E_FAIL);
*pDimension = 0;
{
WCHAR achPrefix[_MAX_ATTRIBUTE_LEN];
CAutoBSTR bstrtempType;
CAutoP<long> pDim(NULL);
CHK(_WSDLUtilSplitQName(bstrType, achPrefix, &m_bstrTypeName));
CHK (_XSDFindURIForPrefix(pArraySchema, achPrefix, &m_bstrTypeURI));
// now figure out the dimension thing
pDimension++; // points to the beginning of the dimension string
CHK_BOOL(*pDimension, E_INVALIDARG); // certainly do not expect the end of string here
CHK(ParseArrayDimensions(pDimension, &m_lDimensions, &pDim));
m_pabound = (SAFEARRAYBOUND*)new BYTE[m_lDimensions * sizeof(SAFEARRAYBOUND)];
CHK_BOOL(m_pabound, E_OUTOFMEMORY);
// now we have to verify the information and move it into the
// member structures
for (long lc = 0; lc < m_lDimensions; lc ++)
{
// if ( (pDim[lc] == -1) && (lc != 0) )
// {
// CHK (DISP_E_BADINDEX);
// }
m_pabound[lc].cElements = pDim[lc];
m_pabound[lc].lLbound = 0;
TRACE ( ("dim: %d cElemts: %d lLBound: %d type: %S %S\n", lc,
m_pabound[m_lDimensions-1].cElements, m_pabound[m_lDimensions-1].lLbound, m_bstrTypeName, m_bstrTypeURI) );
}
}
m_soaparraydef = TRUE;
}
Cleanup:
ASSERT(SUCCEEDED(hr));
return (hr);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: HRESULT CSafearrayMapper::read(IXMLDOMNode *_pNodeOfMapper, BSTR bstrEncoding, enEncodingStyle enStyle, long lFlags, VARIANT * pvar)
//
// parameters:
//
// description:
// reading a string out of a soap message
//
// returns:
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CSafearrayMapper::read(IXMLDOMNode *_pNodeOfMapper, BSTR bstrEncoding, enEncodingStyle enStyle, long lFlags, VARIANT * pvar)
{
HRESULT hr = E_FAIL;
CAutoRefc<IXMLDOMNode> pTemp(NULL);
CAutoRefc<IXMLDOMNode> pChild(NULL);
CAutoRefc<ISoapTypeMapper> ptm(NULL);
CAutoRefc<IXMLDOMNode> pNodeOfMapper(_pNodeOfMapper);
SAFEARRAY * psa = NULL;
VARTYPE vartype;
DOMNodeType dnt;
long lDimension;
BOOL bDoSoapEncoding = FALSE;
CAutoP<long> pIndicesHigh(NULL);
CAutoP<SAFEARRAYBOUND> pabound(NULL);
CAutoP<long> pIndices(NULL);
XPathState xp;
// make sure we got a node
CHK_BOOL(pNodeOfMapper, E_INVALIDARG);
// and create an additional refcount, since we are handling it in a CAutoRefc
pNodeOfMapper->AddRef();
// follow the Href if necessary
CHK (FollowHref(&pNodeOfMapper));
showNode(pNodeOfMapper);
CHK (xp.init(pNodeOfMapper));
CHK (xp.addNamespace(g_pwstrXpathEnv));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -