Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

557 lines
18 KiB

/////////////////////////////////////////////////////////
// TestITN_CHS.cpp : Implementation of CTestITN_CHS
//
// ITN Interpretor for Simplified Chinese:
//
// Integer,
// Decimal,
// Percent,
// Ratio,
// Fraction,
// Minus number,
// Time
//
/////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Itngram_CHS.h"
#include "TestITN_CHS.h"
#include "sphelper.h"
#include "test_CHS.h"
/////////////////////////////////////////////////////////////////////////////
// CTestITN_CHS
/****************************************************************************
* CTestITN_CHS::InitGrammar *
*-------------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
STDMETHODIMP CTestITN_CHS::InitGrammar(const WCHAR * pszGrammarName, const void ** pvGrammarData)
{
HRESULT hr = S_OK;
HRSRC hResInfo = ::FindResource(_Module.GetModuleInstance(), _T("TEST"), _T("ITNGRAMMAR"));
if (hResInfo)
{
HGLOBAL hData = ::LoadResource(_Module.GetModuleInstance(), hResInfo);
if (hData)
{
*pvGrammarData = ::LockResource(hData);
if (*pvGrammarData == NULL)
{
hr = HRESULT_FROM_WIN32(::GetLastError());
}
}
else
{
hr = HRESULT_FROM_WIN32(::GetLastError());
}
}
else
{
hr = HRESULT_FROM_WIN32(::GetLastError());
}
return hr;
}
/****************************************************************************
* CTestITN_CHS::Interpret *
*-----------------------*
* Description:
*
* Returns:
*
********************************************************************* RAL ***/
class CSpPhrasePtrTemp : public CSpPhrasePtr
{
public:
const WCHAR * TextValueOfId(ULONG IdProp);
const double DoubleValueOfId(ULONG IdProp);
const ULONGLONG ULongLongValueOfId(ULONG IdProp);
HRESULT ElementInfoOfId(ULONG IdProp, ULONG *pulFirstElement, ULONG *pulCountOfElements);
private:
const SPPHRASEPROPERTY * FindPropertyById(ULONG IdProp);
const SPPHRASEPROPERTY * FindPropertyByIdHelper(ULONG IdProp, const SPPHRASEPROPERTY *);
};
const WCHAR * CSpPhrasePtrTemp::TextValueOfId(ULONG IdProp)
{
_ASSERT(m_pPhrase);
SPDBG_ASSERT(m_pPhrase);
const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
return pProp ? pProp->pszValue : NULL;
}
const double CSpPhrasePtrTemp::DoubleValueOfId(ULONG IdProp)
{
SPDBG_ASSERT(m_pPhrase);
const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
return pProp ? pProp->vValue.dblVal : 0;
}
const ULONGLONG CSpPhrasePtrTemp::ULongLongValueOfId(ULONG IdProp)
{
SPDBG_ASSERT(m_pPhrase);
const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
return pProp ? pProp->vValue.ulVal : 0;
}
HRESULT CSpPhrasePtrTemp::ElementInfoOfId(ULONG IdProp, ULONG *pulFirstElement, ULONG *pulCountOfElements)
{
_ASSERT(m_pPhrase);
SPDBG_ASSERT(m_pPhrase);
const SPPHRASEPROPERTY * pProp = FindPropertyById(IdProp);
if (pProp)
{
*pulFirstElement = pProp->ulFirstElement;
*pulCountOfElements = pProp->ulCountOfElements;
}
else
{
*pulFirstElement = *pulCountOfElements = 0;
}
return pProp ? S_OK : E_FAIL;
}
const SPPHRASEPROPERTY * CSpPhrasePtrTemp::FindPropertyById(const ULONG IdProp)
{
return FindPropertyByIdHelper(IdProp, m_pPhrase->pProperties);
}
const SPPHRASEPROPERTY * CSpPhrasePtrTemp::FindPropertyByIdHelper(ULONG IdProp, const SPPHRASEPROPERTY * pProp)
{
const SPPHRASEPROPERTY * pRet = NULL;
if (pProp->ulId == IdProp)
{
pRet = pProp;
}
else
{
if (pProp->pFirstChild)
{
pRet = FindPropertyByIdHelper(IdProp, pProp->pFirstChild);
}
if (!pRet && pProp->pNextSibling)
{
pRet = FindPropertyByIdHelper(IdProp, pProp->pNextSibling);
}
}
return pRet;
}
// assume that we have only THOUSANDS(qian), HUNDREDS(bai), TENS(shi), and ONES(ge) here!!
HRESULT ComputeNum9999(const SPPHRASEPROPERTY *pProperties, __int64 *pVal, ULONG *pulLength)
{
ULONG ulVal = 0;
if (pProperties->pFirstChild)
{
for (const SPPHRASEPROPERTY * pProp = pProperties; pProp; pProp = pProp->pNextSibling)
{
if ( 0 != pProp->ulId )
{
SPDBG_ASSERT( pProp->pFirstChild );
SPDBG_ASSERT( VT_UI4 == pProp->vValue.vt );
SPDBG_ASSERT( VT_UI4 == pProp->pFirstChild->vValue.vt );
ulVal += pProp->pFirstChild->vValue.ulVal * pProp->vValue.ulVal;
}
}
}
*pVal = ulVal;
return S_OK;
}
HRESULT ComputeNum10000(const SPPHRASEPROPERTY *pProperties, __int64 *pVal, ULONG *pulLength)
{
HRESULT hr = S_OK;
*pVal = 0;
*pulLength = 0;
WCHAR * pszStopped;
ULONG v2 = wcstol(pProperties->pszValue, &pszStopped, 10);
*pVal += v2;
return hr;
}
/***********************************************************************
* GetMinAndMaxPos *
*-----------------*
* Description:
* Gets the minimum and maximum elements spanned by the
* set of properties
*************************************************************************/
void GetMinAndMaxPos( const SPPHRASEPROPERTY *pProperties,
ULONG *pulMinPos,
ULONG *pulMaxPos )
{
if ( !pulMinPos || !pulMaxPos )
{
return;
}
ULONG ulMin = 9999999;
ULONG ulMax = 0;
for ( const SPPHRASEPROPERTY *pProp = pProperties; pProp; pProp = pProp->pNextSibling )
{
ulMin = __min( ulMin, pProp->ulFirstElement );
ulMax = __max( ulMax, pProp->ulFirstElement + pProp->ulCountOfElements );
}
*pulMinPos = ulMin;
*pulMaxPos = ulMax;
} /* GetMinAndMaxPos */
HRESULT FormatOutput(WCHAR *pBuffer, __int64 Value)
{
swprintf(pBuffer, L"%I64d", Value);
if (Value < 0)
pBuffer++; // keep the '-', replace the rest
int l = wcslen(pBuffer);
if (l<=3)
return S_OK;
int head = l%3;
int block = l/3;
WCHAR buf[100];
wcscpy(buf, pBuffer);
pBuffer[0] = 0;
if (head)
{
wcsncat(pBuffer, buf, head);
pBuffer[head] = 0;
wcscat(pBuffer, L",");
}
for (int i=0; i<block; i++)
{
wcsncat(pBuffer, buf+i*3+head, 3);
if (i<block-1)
wcscat(pBuffer, L",");
}
return S_OK;
}
STDMETHODIMP CTestITN_CHS::Interpret(ISpPhraseBuilder * pPhrase, const ULONG ulFirstElement, const ULONG ulCountOfElements, ISpCFGInterpreterSite * pSite)
{
HRESULT hr = S_OK;
ULONG ulRuleId = 0;
CSpPhrasePtrTemp cpPhrase;
WCHAR szBuff[MAX_PATH], szBuff2[MAX_PATH]; /* pwch;*/
szBuff[0] = 0;
szBuff2[0] = 0;
hr = pPhrase->GetPhrase(&cpPhrase);
m_pSite = pSite;
ULONG ulMinPos;
ULONG ulMaxPos;
GetMinAndMaxPos( cpPhrase->pProperties, &ulMinPos, &ulMaxPos );
if (SUCCEEDED(hr))
{
switch (cpPhrase->Rule.ulId)
{
case GRID_NUMBER: // Number
{
__int64 ulValue = 0;
ULONG ulLength = 0;
//ULONG ulMinPos = 999999999;
//ULONG ulMaxPos = 0;
for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp ? pProp = pProp->pNextSibling : NULL)
{
switch(pProp->ulId)
{
case TENTHOUSANDS_:
{
__int64 v1 = 0;
_ASSERT(pProp);
SPDBG_ASSERT(pProp);
hr = ComputeNum10000(pProp, &v1, &ulLength);
if (SUCCEEDED(hr))
{
ulValue += v1 * 10000;
}
}
break;
case TENTHOUSANDS:
{
__int64 v1 = 0;
_ASSERT(pProp->pFirstChild);
SPDBG_ASSERT(pProp->pFirstChild);
hr = ComputeNum9999(pProp->pFirstChild, &v1, &ulLength);
if (SUCCEEDED(hr))
{
ulValue += v1 * 10000;
}
}
break;
case HUNDREDMILLIONS:
{
__int64 v1 = 0;
_ASSERT(pProp->pFirstChild);
SPDBG_ASSERT(pProp->pFirstChild);
hr = ComputeNum9999(pProp->pFirstChild, &v1, &ulLength);
if (SUCCEEDED(hr))
{
ulValue += v1 * 100000000;
}
}
break;
case ONES:
{
__int64 v1 = 0;
SPDBG_ASSERT(pProp->pFirstChild);
hr = ComputeNum9999(pProp->pFirstChild, &v1, &ulLength);
if (SUCCEEDED(hr))
{
ulValue += v1;
pProp = NULL;
}
}
break;
case ONES_THOUSANDS:
{
SPDBG_ASSERT(pProp->pFirstChild);
ulValue += pProp->pFirstChild->vValue.ulVal;
pProp = NULL;
}
break;
case THOUSANDS:
case HUNDREDS:
default:
_ASSERT(false);
SPDBG_ASSERT(false);
}
}
ATLTRACE(L"GRID_NUMBER: %d\t(%d + %d)\n", ulValue, ulMinPos, ulMaxPos - ulMinPos);
FormatOutput(szBuff, ulValue);
}
break;
case GRID_DECIMAL:
{
szBuff2[0] = 0;
for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
{
switch (pProp->ulId)
{
case INTEGER:
{
wcscpy(szBuff, pProp->pszValue);
wcscat(szBuff, L".");
}
break;
default:
{
wcscat(szBuff2, pProp->pszValue);
}
break;
}
}
ATLTRACE(L"GRID_DECIMAL");
wcscat(szBuff, szBuff2);
}
break;
case PERCENT:
{
for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
{
switch (pProp->ulId)
{
case DECIMAL:
case INTEGER:
{
wcscpy(szBuff, pProp->pszValue);
wcscat(szBuff, L"%");
}
break;
default:
break;
}
}
ATLTRACE(L"PERCENT");
}
break;
case PERCENT100:
{
ATLTRACE(L"PERCENT100");
wcscpy(szBuff, L"100%");
}
break;
case RATIO:
{
for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
{
switch (pProp->ulId)
{
case RATIO1:
wcscpy(szBuff, pProp->pszValue);
break;
case RATIO2:
wcscpy(szBuff2, pProp->pszValue);
break;
default:
break;
}
}
ATLTRACE(L"RATIO");
wcscat(szBuff, L":");
wcscat(szBuff, szBuff2);
}
break;
case FRACTION:
{
for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
{
switch (pProp->ulId)
{
case DENOMINATOR:
wcscpy(szBuff2, pProp->pszValue);
break;
case NUMERATOR:
wcscpy(szBuff, pProp->pszValue);
break;
default:
break;
}
}
ATLTRACE(L"FRACTION");
wcscat(szBuff, L"/");
wcscat(szBuff, szBuff2);
}
break;
case GRID_NUMBER_MINUS:
{
for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
{
switch (pProp->ulId)
{
case POS_OF_MINUS:
wcscpy(szBuff2, pProp->pszValue);
break;
default:
break;
}
}
ATLTRACE(L"GRID_NUMBER_MINUS");
wcscpy(szBuff, L"-");
wcscat(szBuff, szBuff2);
}
break;
case TIME:
{
for (const SPPHRASEPROPERTY * pProp = cpPhrase->pProperties; pProp; pProp = pProp->pNextSibling)
{
switch (pProp->ulId)
{
case HOUR:
wcscpy(szBuff, pProp->pszValue);
break;
case MINUTE:
wcscpy(szBuff2, pProp->pszValue);
break;
default:
break;
}
}
ATLTRACE(L"TIME");
wcscat(szBuff, L":");
wcscat(szBuff, szBuff2);
}
break;
default:
_ASSERT(FALSE);
break;
}
hr = AddPropertyAndReplacement( szBuff, 0,
ulMinPos, ulMaxPos, ulMinPos, ulMaxPos - ulMinPos );//ulFirstElement, ulCountOfElements );
}
return hr;
}
/***********************************************************************
* CTestITN_CHS::AddPropertyAndReplacement *
*---------------------------------------*
* Description:
* Takes all of the info that we want to pass into the
* engine site, forms the SPPHRASEPROPERTY and
* SPPHRASERREPLACEMENT, and adds them to the engine site
* Return:
* Return values of ISpCFGInterpreterSite::AddProperty()
* and ISpCFGInterpreterSite::AddTextReplacement()
*************************************************************************/
HRESULT CTestITN_CHS::AddPropertyAndReplacement( const WCHAR *szBuff,
const DOUBLE dblValue,
const ULONG ulMinPos,
const ULONG ulMaxPos,
const ULONG ulFirstElement,
const ULONG ulCountOfElements )
{
// Add the property
SPPHRASEPROPERTY prop;
memset(&prop,0,sizeof(prop));
prop.pszValue = szBuff;
prop.vValue.vt = VT_R8;
prop.vValue.dblVal = dblValue;
prop.ulFirstElement = ulMinPos;
prop.ulCountOfElements = ulMaxPos - ulMinPos;
HRESULT hr = m_pSite->AddProperty(&prop);
if (SUCCEEDED(hr))
{
SPPHRASEREPLACEMENT repl;
memset(&repl,0, sizeof(repl));
//repl.bDisplayAttributes = SPAF_ONE_TRAILING_SPACE;
// No space after the ITNed string in Chinese
repl.bDisplayAttributes = 0;
repl.pszReplacementText = szBuff;
repl.ulFirstElement = ulFirstElement;
repl.ulCountOfElements = ulCountOfElements;
hr = m_pSite->AddTextReplacement(&repl);
}
return hr;
} /* CTestITN_CHS::AddPropertyAndReplacement */