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.
2336 lines
97 KiB
2336 lines
97 KiB
#include "stdafx.h"
|
|
|
|
#ifndef StdSentEnum_h
|
|
#include "stdsentenum.h"
|
|
#endif
|
|
|
|
#pragma warning (disable : 4296)
|
|
|
|
/***********************************************************************************************
|
|
* IsNumericCompactDate *
|
|
*----------------------*
|
|
* Description:
|
|
* Checks the incoming Item's text to determine whether or not it
|
|
* is a Date, and if so, which type.
|
|
*
|
|
* RegExp:
|
|
* {[1-12]{'/' || '-' || '.'}[1-31]{'/' || '-' || '.'}[0-9999]} ||
|
|
* {[1-31]{'/' || '-' || '.'}[1-12]{'/' || '-' || '.'}[0-9999]} ||
|
|
* {[0-9999]{'/' || '-' || '.'}[1-12]{'/' || '-' || '.'}[1-31]}
|
|
*
|
|
* Types assigned:
|
|
* Date
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::IsNumericCompactDate( TTSItemInfo*& pItemNormInfo, const WCHAR* Context,
|
|
CSentItemMemory& MemoryManager )
|
|
{
|
|
SPDBG_FUNC( "CStdSentEnum::IsNumericCompactDate" );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
WCHAR *pFirstChunk = 0, *pSecondChunk = 0, *pThirdChunk = 0, *pLeftOver = 0, *pDelimiter = 0;
|
|
ULONG ulFirst = 0;
|
|
ULONG ulSecond = 0;
|
|
ULONG ulThird = 0;
|
|
ULONG ulTokenLen = (ULONG)(m_pEndOfCurrItem - m_pNextChar);
|
|
bool bThree = false, bTwo = false;
|
|
bool fMonthDayYear = false, fDayMonthYear = false, fYearMonthDay = false;
|
|
|
|
//--- Max length of a string matching the regexp is 10 characters
|
|
if ( ulTokenLen > 10 )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
//--- Get the preferred order of the compact Date
|
|
if ( Context != NULL )
|
|
{
|
|
if ( _wcsicmp( Context, L"Date_MDY" ) == 0 )
|
|
{
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( _wcsicmp( Context, L"Date_DMY" ) == 0 )
|
|
{
|
|
fDayMonthYear = true;
|
|
}
|
|
else if ( _wcsicmp( Context, L"Date_YMD" ) == 0 )
|
|
{
|
|
fYearMonthDay = true;
|
|
}
|
|
else
|
|
{
|
|
if ( m_eShortDateOrder & MONTH_DAY_YEAR )
|
|
{
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
|
|
{
|
|
fDayMonthYear = true;
|
|
}
|
|
else
|
|
{
|
|
fYearMonthDay = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( m_eShortDateOrder & MONTH_DAY_YEAR )
|
|
{
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
|
|
{
|
|
fDayMonthYear = true;
|
|
}
|
|
else
|
|
{
|
|
fYearMonthDay = true;
|
|
}
|
|
}
|
|
|
|
pFirstChunk = (WCHAR*) m_pNextChar;
|
|
|
|
//----------------------------------------------
|
|
// First Try To Get Three Numerical Values
|
|
//----------------------------------------------
|
|
|
|
ulFirst = my_wcstoul( pFirstChunk, &pSecondChunk );
|
|
if ( pFirstChunk != pSecondChunk &&
|
|
( pSecondChunk - pFirstChunk ) <= 4 )
|
|
{
|
|
pDelimiter = pSecondChunk;
|
|
if ( MatchDateDelimiter( &pSecondChunk ) )
|
|
{
|
|
ulSecond = my_wcstoul( pSecondChunk, &pThirdChunk );
|
|
if ( pSecondChunk != pThirdChunk &&
|
|
( pThirdChunk - pSecondChunk ) <= 4 )
|
|
{
|
|
if ( *pThirdChunk == *pDelimiter &&
|
|
MatchDateDelimiter( &pThirdChunk ) )
|
|
{
|
|
ulThird = my_wcstoul( pThirdChunk, &pLeftOver );
|
|
if ( pThirdChunk != pLeftOver &&
|
|
pLeftOver == ( pFirstChunk + ulTokenLen ) &&
|
|
( pLeftOver - pThirdChunk ) <= 4 )
|
|
{
|
|
//--- Successfully Matched { d+{'/' || '-' || '.'}d+{'/' || '-' || '.'}d+ }
|
|
bThree = true;
|
|
}
|
|
else
|
|
{
|
|
//--- Digit-String Delimiter Digit-String Delimiter non-digit cannot be a Date,
|
|
//--- nor can Digit-String Delimiter Digit-String Delimiter Digit-String String
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( pThirdChunk == m_pEndOfCurrItem )
|
|
{
|
|
//--- Successfully Matched { d+{'/' || '-' || '.'}d+ }
|
|
bTwo = true;
|
|
}
|
|
else
|
|
{
|
|
//--- Digit-String Delimiter Digit-String non-delimiter cannot be a Date
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//--- Digit-String followed by non-delimiter cannot be a Date
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------
|
|
// Now Figure Out What To Do With The Values
|
|
//------------------------------------------------
|
|
|
|
//--- Matched a Month, Day, and Year ---//
|
|
if ( SUCCEEDED( hr ) &&
|
|
bThree )
|
|
{
|
|
//--- Try to valiDate values
|
|
ULONG ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk - 1);
|
|
ULONG ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk - 1);
|
|
ULONG ulThirdChunkLength = (ULONG)(pLeftOver - pThirdChunk);
|
|
|
|
//--- Preferred order is Month Day Year
|
|
if (fMonthDayYear)
|
|
{
|
|
//--- Try Month Day Year, then Day Month Year, then Year Month Day
|
|
if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
|
|
( ulFirstChunkLength <= 3 ) &&
|
|
( DAYMIN <= ulSecond && ulSecond <= DAYMAX) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
NULL;
|
|
}
|
|
else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 3 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = true;
|
|
}
|
|
else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength >= 2 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
|
|
( ulThirdChunkLength <= 3 ) )
|
|
{
|
|
fMonthDayYear = false;
|
|
fYearMonthDay = true;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
//--- Preferred order is Day Month Year
|
|
else if ( fDayMonthYear )
|
|
{
|
|
//--- Try Day Month Year, then Month Day Year, then Year Month Day
|
|
if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 3 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
NULL;
|
|
}
|
|
else if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
|
|
( ulFirstChunkLength <= 3 ) &&
|
|
( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
fDayMonthYear = false;
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength >= 2 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
|
|
( ulThirdChunkLength <= 3 ) )
|
|
{
|
|
fDayMonthYear = false;
|
|
fYearMonthDay = true;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
//--- Preferred order is Year Month Day
|
|
else if (fYearMonthDay)
|
|
{
|
|
//--- Try Year Month Day, then Month Day Year, then Day Month Year
|
|
if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength >= 2 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
|
|
( ulThirdChunkLength <= 3 ) )
|
|
{
|
|
NULL;
|
|
}
|
|
else if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
|
|
( ulFirstChunkLength <= 3 ) &&
|
|
( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
fYearMonthDay = false;
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 3 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 3 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
fYearMonthDay = false;
|
|
fDayMonthYear = true;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
//--- Fill out DateItemInfo structure appropriately.
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
|
|
pItemNormInfo->Type = eDATE;
|
|
if ( fMonthDayYear )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( *pSecondChunk == L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk + 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulSecondChunkLength;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pSecondChunk +
|
|
ulSecondChunkLength;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
|
|
}
|
|
}
|
|
}
|
|
else if ( fDayMonthYear )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( *pFirstChunk == L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk + 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulFirstChunkLength;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pFirstChunk +
|
|
ulFirstChunkLength;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
|
|
}
|
|
}
|
|
}
|
|
else if ( fYearMonthDay )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( *pThirdChunk == L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk + 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulThirdChunkLength;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pThirdChunk +
|
|
ulThirdChunkLength;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pFirstChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulFirstChunkLength;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//--- Matched just a Month and Day, or a Month and Year ---//
|
|
else if ( SUCCEEDED( hr ) &&
|
|
Context &&
|
|
bTwo )
|
|
{
|
|
ULONG ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk - 1);
|
|
ULONG ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
|
|
|
|
if ( _wcsicmp(Context, L"Date_MD") == 0 )
|
|
{
|
|
if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
|
|
( ulFirstChunkLength <= 2 ) &&
|
|
( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
|
|
( ulSecondChunkLength <= 2 ) )
|
|
{
|
|
//--- Successfully matched a month and day
|
|
pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
|
|
pItemNormInfo->Type = eDATE;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( pSecondChunk[0] == L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk + 1;
|
|
ulSecondChunkLength--;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulSecondChunkLength;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar =
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar + ulSecondChunkLength;
|
|
}
|
|
}
|
|
|
|
}
|
|
else // values out of range
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else if ( _wcsicmp(Context, L"Date_DM") == 0 )
|
|
{
|
|
if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 2 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 2 ) )
|
|
{
|
|
//--- Successfully matched a month and day
|
|
pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
|
|
pItemNormInfo->Type = eDATE;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( m_pNextChar[0] == L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk + 1;
|
|
ulFirstChunkLength--;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = ulFirstChunkLength;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar =
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar + ulFirstChunkLength;
|
|
}
|
|
}
|
|
}
|
|
else // values out of range
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else if ( _wcsicmp(Context, L"Date_MY") == 0 )
|
|
{
|
|
if ( ( MONTHMIN <= ulFirst && ulFirst <= MONTHMAX ) &&
|
|
( ulFirstChunkLength <= 2 ) &&
|
|
( YEARMIN <= ulSecond && ulSecond <= YEARMAX ) &&
|
|
( ulSecondChunkLength >= 2 ) )
|
|
{
|
|
//--- Successfully matched a month and year
|
|
pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
|
|
pItemNormInfo->Type = eDATE;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pSecondChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulSecondChunkLength;
|
|
}
|
|
}
|
|
}
|
|
else // values out of range
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else if ( _wcsicmp(Context, L"Date_YM") == 0 )
|
|
{
|
|
if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength >= 2 ) &&
|
|
( MONTHMIN <= ulSecond && ulSecond <= MONTHMAX ) &&
|
|
( ulSecondChunkLength <= 2 ) )
|
|
{
|
|
//--- Successfully matched a month and year
|
|
pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
|
|
pItemNormInfo->Type = eDATE;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pYear, sizeof(TTSYearItemInfo) );
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pFirstChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulFirstChunkLength;
|
|
}
|
|
}
|
|
}
|
|
else // values out of range
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
//--- not a date unless context specifies...
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
} /* IsNumericCompactDate */
|
|
|
|
/***********************************************************************************************
|
|
* IsMonthStringCompactDate *
|
|
*--------------------------*
|
|
* Description:
|
|
* Checks the incoming Item's text to determine whether or not it
|
|
* is a Date with a string for the month, and if so, which type.
|
|
*
|
|
* RegExp:
|
|
* {[MonthString]{'/' || '-' || '.'}[1-31]{'/' || '-' || '.'}[0-9999]} ||
|
|
* {[1-31]{'/' || '-' || '.'}[MonthString]{'/' || '-' || '.'}[0-9999]} ||
|
|
* {[0-9999]{'/' || '-' || '.'}[MonthString]{'/' || '-' || '.'}[1-31]}
|
|
*
|
|
* Types assigned:
|
|
* Date
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::IsMonthStringCompactDate( TTSItemInfo*& pItemNormInfo, const WCHAR* Context,
|
|
CSentItemMemory& MemoryManager )
|
|
{
|
|
SPDBG_FUNC( "DateNorm.cpp IsMonthStringCompactDate" );
|
|
|
|
HRESULT hr = S_OK;
|
|
WCHAR *pFirstChunk = 0, *pSecondChunk = 0, *pThirdChunk = 0, *pLeftOver = 0;
|
|
ULONG ulFirst = 0;
|
|
ULONG ulSecond = 0;
|
|
ULONG ulThird = 0;
|
|
ULONG ulTokenLen = (ULONG)(m_pEndOfCurrItem - m_pNextChar);
|
|
ULONG ulFirstChunkLength = 0, ulSecondChunkLength = 0, ulThirdChunkLength = 0;
|
|
bool fMonthDayYear = false, fDayMonthYear = false, fYearMonthDay = false;
|
|
|
|
//--- Max length of a Date matching this regexp is 17 characters
|
|
if ( ulTokenLen > 17 )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
//--- Get preferred order of Month, Day, and Year for this user
|
|
if (Context != NULL)
|
|
{
|
|
if ( _wcsicmp( Context, L"Date_MDY" ) == 0 )
|
|
{
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( _wcsicmp( Context, L"Date_DMY" ) == 0 )
|
|
{
|
|
fDayMonthYear = true;
|
|
}
|
|
else if ( _wcsicmp( Context, L"Date_YMD" ) == 0 )
|
|
{
|
|
fYearMonthDay = true;
|
|
}
|
|
else
|
|
{
|
|
if ( m_eShortDateOrder & MONTH_DAY_YEAR )
|
|
{
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
|
|
{
|
|
fDayMonthYear = true;
|
|
}
|
|
else
|
|
{
|
|
fYearMonthDay = true;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( m_eShortDateOrder & MONTH_DAY_YEAR )
|
|
{
|
|
fMonthDayYear = true;
|
|
}
|
|
else if ( m_eShortDateOrder & DAY_MONTH_YEAR )
|
|
{
|
|
fDayMonthYear = true;
|
|
}
|
|
else
|
|
{
|
|
fYearMonthDay = true;
|
|
}
|
|
}
|
|
|
|
pFirstChunk = (WCHAR*) m_pNextChar;
|
|
pSecondChunk = pFirstChunk;
|
|
|
|
//--- Try MonthString-Day-Year format
|
|
if ( iswalpha( *pFirstChunk ) )
|
|
{
|
|
ulFirst = MatchMonthString( pSecondChunk, ulTokenLen );
|
|
if ( ulFirst )
|
|
{
|
|
ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk);
|
|
if ( MatchDateDelimiter( &pSecondChunk ) )
|
|
{
|
|
pThirdChunk = pSecondChunk;
|
|
ulSecond = my_wcstoul( pSecondChunk, &pThirdChunk );
|
|
if ( pSecondChunk != pThirdChunk &&
|
|
pThirdChunk - pSecondChunk <= 2 )
|
|
{
|
|
ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
|
|
if ( MatchDateDelimiter( &pThirdChunk ) )
|
|
{
|
|
ulThird = my_wcstoul( pThirdChunk, &pLeftOver );
|
|
if ( pThirdChunk != pLeftOver &&
|
|
pLeftOver - pThirdChunk <= 4 )
|
|
{
|
|
ulThirdChunkLength = (ULONG)(pLeftOver - pThirdChunk);
|
|
//--- May have matched a month, day and year - valiDate values
|
|
if ( ( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
|
|
( ulSecondChunkLength <= 2 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
//--- Successfully matched a month, day and year
|
|
fMonthDayYear = true;
|
|
fDayMonthYear = false;
|
|
fYearMonthDay = false;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( !Context ||
|
|
( Context &&
|
|
_wcsicmp( Context, L"Date_MD" ) == 0 ) )
|
|
{
|
|
if ( ( DAYMIN <= ulSecond && ulSecond <= DAYMAX ) &&
|
|
( ulSecondChunkLength <= 2 ) )
|
|
{
|
|
fMonthDayYear = true;
|
|
fDayMonthYear = false;
|
|
fYearMonthDay = false;
|
|
pThirdChunk = NULL;
|
|
}
|
|
else
|
|
{
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = false;
|
|
fYearMonthDay = true;
|
|
pFirstChunk = pSecondChunk;
|
|
ulFirstChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
|
|
ulSecond = ulFirst;
|
|
pThirdChunk = NULL;
|
|
}
|
|
}
|
|
else if ( Context &&
|
|
_wcsicmp( Context, L"Date_MY" ) == 0 )
|
|
{
|
|
if ( ( YEARMIN <= ulSecond && ulSecond <= YEARMAX ) &&
|
|
( ulSecondChunkLength <= 4 ) )
|
|
{
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = false;
|
|
fYearMonthDay = true;
|
|
pFirstChunk = pSecondChunk;
|
|
ulFirstChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
|
|
ulSecond = ulFirst;
|
|
pThirdChunk = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
}
|
|
else if ( pSecondChunk != pThirdChunk &&
|
|
pThirdChunk - pSecondChunk <= 4 )
|
|
{
|
|
if ( ( YEARMIN <= ulSecond && ulSecond <= YEARMAX ) )
|
|
{
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = false;
|
|
fYearMonthDay = true;
|
|
pFirstChunk = pSecondChunk;
|
|
ulFirstChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
|
|
ulSecond = ulFirst;
|
|
pThirdChunk = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
//--- Try Day-MonthString-Year and Year-MonthString-Day Formats
|
|
else if ( isdigit( *pFirstChunk ) )
|
|
{
|
|
ulFirst = my_wcstoul( pFirstChunk, &pSecondChunk );
|
|
if ( pFirstChunk != pSecondChunk &&
|
|
pSecondChunk - pFirstChunk <= 4 )
|
|
{
|
|
ulFirstChunkLength = (ULONG)(pSecondChunk - pFirstChunk);
|
|
if ( MatchDateDelimiter( &pSecondChunk ) )
|
|
{
|
|
pThirdChunk = pSecondChunk;
|
|
ulSecond = MatchMonthString( pThirdChunk, ulTokenLen - ulFirstChunkLength );
|
|
if ( ulSecond )
|
|
{
|
|
ulSecondChunkLength = (ULONG)(pThirdChunk - pSecondChunk);
|
|
if ( MatchDateDelimiter( &pThirdChunk ) )
|
|
{
|
|
ulThird = my_wcstoul( pThirdChunk, &pLeftOver );
|
|
if ( pThirdChunk != pLeftOver &&
|
|
pLeftOver - pThirdChunk <= 4 )
|
|
{
|
|
ulThirdChunkLength = (ULONG)(pLeftOver - pThirdChunk);
|
|
//--- May have matched a month, day, and year - valiDate values
|
|
if ( fDayMonthYear ||
|
|
fMonthDayYear )
|
|
{
|
|
//--- Preferred format is Month Day Year, or Day Month Year - in either case
|
|
//--- Day Month Year is preferable to Year Month Day
|
|
if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 2 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
//--- Successfully matched a day, month and year
|
|
fDayMonthYear = true;
|
|
fMonthDayYear = false;
|
|
fYearMonthDay = false;
|
|
}
|
|
else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength >= 2 ) &&
|
|
( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
|
|
( ulThirdChunkLength <= 2 ) )
|
|
{
|
|
//--- Successfully matched a year, month and day
|
|
fYearMonthDay = true;
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = false;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else // fYearMonthDay
|
|
{
|
|
//--- Preferred format is Year Month Day
|
|
if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength >= 2 ) &&
|
|
( DAYMIN <= ulThird && ulThird <= DAYMAX ) &&
|
|
( ulThirdChunkLength <= 2 ) )
|
|
{
|
|
//--- Successfully matched a year, month, and day
|
|
fYearMonthDay = true;
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = false;
|
|
}
|
|
else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 2 ) &&
|
|
( YEARMIN <= ulThird && ulThird <= YEARMAX ) &&
|
|
( ulThirdChunkLength >= 2 ) )
|
|
{
|
|
//--- Successfully matched a day, month, and year
|
|
fDayMonthYear = true;
|
|
fMonthDayYear = false;
|
|
fYearMonthDay = false;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
//--- Matched two - either Day-Monthstring or Year-Monthstring
|
|
else
|
|
{
|
|
if ( !Context ||
|
|
( Context &&
|
|
_wcsicmp( Context, L"Date_DM" ) == 0 ) )
|
|
{
|
|
//--- Preferred format is Month Day Year, or Day Month Year - in either case
|
|
//--- Day Month Year is preferable to Year Month Day
|
|
if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 2 ) )
|
|
{
|
|
//--- Successfully matched a day, month and year
|
|
fDayMonthYear = true;
|
|
fMonthDayYear = false;
|
|
fYearMonthDay = false;
|
|
pThirdChunk = NULL;
|
|
}
|
|
else if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength <= 4 ) )
|
|
{
|
|
//--- Successfully matched a year, month and day
|
|
fYearMonthDay = true;
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = false;
|
|
pThirdChunk = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else if ( Context &&
|
|
_wcsicmp( Context, L"Date_YM" ) == 0 )
|
|
{
|
|
//--- Preferred format is Year Month Day
|
|
if ( ( YEARMIN <= ulFirst && ulFirst <= YEARMAX ) &&
|
|
( ulFirstChunkLength <= 4 ) )
|
|
{
|
|
//--- Successfully matched a year, month, and day
|
|
fYearMonthDay = true;
|
|
fMonthDayYear = false;
|
|
fDayMonthYear = false;
|
|
pThirdChunk = NULL;
|
|
}
|
|
else if ( ( DAYMIN <= ulFirst && ulFirst <= DAYMAX ) &&
|
|
( ulFirstChunkLength <= 2 ) )
|
|
{
|
|
//--- Successfully matched a day, month, and year
|
|
fDayMonthYear = true;
|
|
fMonthDayYear = false;
|
|
fYearMonthDay = false;
|
|
pThirdChunk = NULL;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
//--- Fill out DateItemInfo structure appropriately.
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pItemNormInfo = (TTSDateItemInfo*) MemoryManager.GetMemory( sizeof(TTSDateItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDateItemInfo) );
|
|
pItemNormInfo->Type = eDATE;
|
|
if ( fMonthDayYear )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulFirst;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( ulSecondChunkLength == 2 )
|
|
{
|
|
if ( *pSecondChunk != L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 2;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk + 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pSecondChunk + 2;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pSecondChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pSecondChunk + 1;
|
|
}
|
|
if ( pThirdChunk )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear = NULL;
|
|
}
|
|
}
|
|
}
|
|
else if ( fDayMonthYear )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( ulFirstChunkLength == 2 )
|
|
{
|
|
if ( *pFirstChunk != L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 2;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk + 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pFirstChunk + 2;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pFirstChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pFirstChunk + 1;
|
|
}
|
|
if ( pThirdChunk )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pThirdChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulThirdChunkLength;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear = NULL;
|
|
}
|
|
}
|
|
}
|
|
else if ( fYearMonthDay )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->ulMonthIndex = ulSecond;
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
if ( pThirdChunk )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay =
|
|
(TTSIntegerItemInfo*) MemoryManager.GetMemory( sizeof(TTSIntegerItemInfo), &hr );
|
|
if ( ulThirdChunkLength == 2 )
|
|
{
|
|
ZeroMemory( ( (TTSDateItemInfo*) pItemNormInfo )->pDay, sizeof(TTSIntegerItemInfo) );
|
|
if ( *pThirdChunk != L'0' )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 2;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk + 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pThirdChunk + 2;
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pStartChar = pThirdChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->lLeftOver = 1;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay->pEndChar = pThirdChunk + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pDay = NULL;
|
|
}
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear =
|
|
(TTSYearItemInfo*) MemoryManager.GetMemory( sizeof(TTSYearItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->pYear = pFirstChunk;
|
|
( (TTSDateItemInfo*) pItemNormInfo )->pYear->ulNumDigits = ulFirstChunkLength;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//--- should never get here.
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
} /* IsMonthStringCompactDate */
|
|
|
|
/***********************************************************************************************
|
|
* IsLongFormDate_DMDY *
|
|
*---------------------*
|
|
* Description:
|
|
* Checks the incoming Item's text to determine whether or not it
|
|
* is a long form Date.
|
|
*
|
|
* RegExp:
|
|
* [[DayString][,]?]? [MonthString][,]? [Day][,]? [Year]?
|
|
*
|
|
* Types assigned:
|
|
* Date
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::IsLongFormDate_DMDY( TTSItemInfo*& pItemNormInfo, CSentItemMemory& MemoryManager,
|
|
CWordList& WordList )
|
|
{
|
|
SPDBG_FUNC( "CStdSentEnum::IsLongFormDate_DMDY" );
|
|
HRESULT hr = S_OK;
|
|
WCHAR *pDayString = NULL, *pMonthString = NULL, *pDay = NULL, *pYear = NULL;
|
|
ULONG ulDayLength = 0, ulYearLength = 0;
|
|
long lDayString = -1, lMonthString = -1, lDay = 0, lYear = 0;
|
|
const WCHAR *pStartChar = m_pNextChar, *pEndOfItem = m_pEndOfCurrItem, *pEndChar = m_pEndChar;
|
|
const WCHAR *pTempEndChar = NULL, *pTempEndOfItem = NULL;
|
|
const SPVTEXTFRAG* pFrag = m_pCurrFrag, *pTempFrag = NULL;
|
|
const SPVSTATE *pDayStringXMLState = NULL, *pMonthStringXMLState = NULL, *pDayXMLState = NULL;
|
|
const SPVSTATE *pYearXMLState = NULL;
|
|
CItemList PostDayStringList, PostMonthStringList, PostDayList;
|
|
BOOL fNoYear = false;
|
|
|
|
//--- Try to match Day String
|
|
pDayString = (WCHAR*) pStartChar;
|
|
lDayString = MatchDayString( pDayString, (WCHAR*) pEndOfItem );
|
|
|
|
//--- Failed to match a Day String
|
|
if ( lDayString == 0 )
|
|
{
|
|
pDayString = NULL;
|
|
}
|
|
//--- Matched a Day String, but it wasn't by itself or followed by a comma
|
|
else if ( pDayString != pEndOfItem &&
|
|
( pDayString != pEndOfItem - 1 ||
|
|
*pEndOfItem != L',' ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
//--- Matched a Day String - save XML State and move ahead in text
|
|
else
|
|
{
|
|
pDayString = (WCHAR*) pStartChar;
|
|
pDayStringXMLState = &pFrag->State;
|
|
|
|
pStartChar = pEndOfItem;
|
|
if ( *pStartChar == L',' )
|
|
{
|
|
pStartChar++;
|
|
}
|
|
hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayStringList );
|
|
if ( !pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if ( pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
|
|
}
|
|
}
|
|
|
|
//--- Try to match Month String
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pMonthString = (WCHAR*) pStartChar;
|
|
lMonthString = MatchMonthString( pMonthString, (ULONG)(pEndOfItem - pMonthString) );
|
|
|
|
//--- Failed to match Month String, or Month String was not by itself...
|
|
if ( !lMonthString ||
|
|
( pMonthString != pEndOfItem &&
|
|
( pMonthString != pEndOfItem - 1 ||
|
|
*pMonthString != L',' ) ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
//--- Matched a Month String - save XML State and move ahead in text
|
|
else
|
|
{
|
|
pMonthString = (WCHAR*) pStartChar;
|
|
pMonthStringXMLState = &pFrag->State;
|
|
|
|
pStartChar = pEndOfItem;
|
|
hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostMonthStringList );
|
|
if ( !pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if ( pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
|
|
//--- Strip trailing punctuation, etc. since the next token could be the last one if
|
|
//--- this is just a Monthstring and Day...
|
|
while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
|
|
{
|
|
if ( *(pEndOfItem - 1) != L',' )
|
|
{
|
|
fNoYear = true;
|
|
}
|
|
pEndOfItem--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--- Try to match Day
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
lDay = my_wcstoul( pStartChar, &pDay );
|
|
//--- Matched a Day - save XML State and move ahead in text
|
|
if ( ( DAYMIN <= lDay && lDay <= DAYMAX ) &&
|
|
pDay - pStartChar <= 2 &&
|
|
( pDay == pEndOfItem ||
|
|
( pDay == (pEndOfItem - 1) && *pDay == L',' ) ) )
|
|
{
|
|
if ( pDay == pEndOfItem )
|
|
{
|
|
ulDayLength = (ULONG)(pEndOfItem - pStartChar);
|
|
}
|
|
else if ( pDay == pEndOfItem - 1 )
|
|
{
|
|
ulDayLength = (ULONG)((pEndOfItem - 1) - pStartChar);
|
|
}
|
|
pDay = (WCHAR*) pStartChar;
|
|
pDayXMLState = &pFrag->State;
|
|
|
|
if ( !fNoYear )
|
|
{
|
|
//--- Save pointers, in case there is no year present
|
|
pTempEndChar = pEndChar;
|
|
pTempEndOfItem = pEndOfItem;
|
|
pTempFrag = pFrag;
|
|
|
|
if ( *pEndOfItem == L',' )
|
|
{
|
|
pStartChar = pEndOfItem + 1;
|
|
}
|
|
else
|
|
{
|
|
pStartChar = pEndOfItem;
|
|
}
|
|
hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayList );
|
|
if ( !pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
fNoYear = true;
|
|
pYear = NULL;
|
|
}
|
|
else if ( pStartChar &&
|
|
( SUCCEEDED( hr ) ) )
|
|
{
|
|
pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
|
|
//--- Strip trailing punctuation, since the next token will be the last one
|
|
//--- if this is Monthstring, Day, Year
|
|
while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
|
|
{
|
|
pEndOfItem--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//--- Failed to match a day
|
|
else if ( ( YEARMIN <= lDay && lDay <= YEARMAX ) &&
|
|
pDay - pStartChar <= 4 &&
|
|
pDay == pEndOfItem )
|
|
{
|
|
//--- Successfully matched Month String and Year
|
|
pYearXMLState = &pFrag->State;
|
|
ulYearLength = (ULONG)(pEndOfItem - pStartChar);
|
|
pYear = (WCHAR*) pStartChar;
|
|
//--- Don't try to match a year again
|
|
fNoYear = true;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
//--- Try to match Year
|
|
if ( SUCCEEDED( hr ) &&
|
|
!fNoYear )
|
|
{
|
|
lYear = my_wcstoul( pStartChar, &pYear );
|
|
//--- Matched a Year
|
|
if ( ( YEARMIN <= lYear && lYear <= YEARMAX ) &&
|
|
pYear - pStartChar <= 4 &&
|
|
pYear == pEndOfItem )
|
|
{
|
|
//--- Successfully matched Month String, Day, and Year (and possibly Day String)
|
|
pYearXMLState = &pFrag->State;
|
|
ulYearLength = (ULONG)(pEndOfItem - pStartChar);
|
|
pYear = (WCHAR*) pStartChar;
|
|
}
|
|
else
|
|
{
|
|
//--- Failed to match Year - replace pointers with previous values
|
|
pEndChar = pTempEndChar;
|
|
pEndOfItem = pTempEndOfItem;
|
|
pFrag = pTempFrag;
|
|
pYear = NULL;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
TTSWord Word;
|
|
ZeroMemory( &Word, sizeof(TTSWord) );
|
|
Word.eWordPartOfSpeech = MS_Unknown;
|
|
|
|
pItemNormInfo = (TTSItemInfo*) MemoryManager.GetMemory( sizeof(TTSItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pItemNormInfo->Type = eDATE_LONGFORM;
|
|
|
|
//--- Insert Day String, if present
|
|
if ( pDayString )
|
|
{
|
|
Word.pXmlState = pDayStringXMLState;
|
|
Word.pWordText = g_days[lDayString - 1].pStr;
|
|
Word.ulWordLen = g_days[lDayString - 1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
|
|
//--- Insert Post Day String XML States
|
|
while ( !PostDayStringList.IsEmpty() )
|
|
{
|
|
WordList.AddTail( ( PostDayStringList.RemoveHead() ).Words[0] );
|
|
}
|
|
|
|
//--- Insert Month String
|
|
Word.pXmlState = pMonthStringXMLState;
|
|
Word.pWordText = g_months[lMonthString - 1].pStr;
|
|
Word.ulWordLen = g_months[lMonthString - 1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
|
|
//--- Insert Post Month String XML State
|
|
while ( !PostMonthStringList.IsEmpty() )
|
|
{
|
|
WordList.AddTail( ( PostMonthStringList.RemoveHead() ).Words[0] );
|
|
}
|
|
|
|
SPLISTPOS WordListPos = WordList.GetTailPosition();
|
|
|
|
//--- Expand Day
|
|
if ( ulDayLength == 1 )
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandDigitOrdinal( *pDay, Garbage, WordList );
|
|
}
|
|
else if ( ulDayLength == 2 )
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandTwoOrdinal( pDay, Garbage, WordList );
|
|
}
|
|
|
|
//--- Clean Up Day XML States
|
|
WordList.GetNext( WordListPos );
|
|
while ( WordListPos )
|
|
{
|
|
TTSWord& TempWord = WordList.GetNext( WordListPos );
|
|
TempWord.pXmlState = pDayXMLState;
|
|
}
|
|
|
|
//--- Insert Post Day XML State
|
|
while ( !PostDayList.IsEmpty() )
|
|
{
|
|
WordList.AddTail( ( PostDayList.RemoveHead() ).Words[0] );
|
|
}
|
|
|
|
WordListPos = WordList.GetTailPosition();
|
|
|
|
//--- Expand Year, if present
|
|
if ( pYear )
|
|
{
|
|
TTSYearItemInfo TempYearInfo;
|
|
TempYearInfo.pYear = pYear;
|
|
TempYearInfo.ulNumDigits = ulYearLength;
|
|
hr = ExpandYear( &TempYearInfo, WordList );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
//--- Clean Up Year XML States
|
|
WordList.GetNext( WordListPos );
|
|
while ( WordListPos )
|
|
{
|
|
TTSWord& TempWord = WordList.GetNext( WordListPos );
|
|
TempWord.pXmlState = pYearXMLState;
|
|
}
|
|
}
|
|
}
|
|
//--- Advance pointers
|
|
m_pCurrFrag = pFrag;
|
|
m_pEndChar = pEndChar;
|
|
m_pEndOfCurrItem = pEndOfItem;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
} /* IsLongFormDate_DMDY */
|
|
|
|
/***********************************************************************************************
|
|
* IsLongFormDate_DDMY *
|
|
*---------------------*
|
|
* Description:
|
|
* Checks the incoming Item's text to determine whether or not it
|
|
* is a long form Date.
|
|
*
|
|
* RegExp:
|
|
* [[DayString][,]?]? [Day][,]? [MonthString][,]? [Year]?
|
|
*
|
|
* Types assigned:
|
|
* Date
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::IsLongFormDate_DDMY( TTSItemInfo*& pItemNormInfo, CSentItemMemory& MemoryManager,
|
|
CWordList& WordList )
|
|
{
|
|
SPDBG_FUNC( "CStdSentEnum::IsLongFormDate_DDMY" );
|
|
HRESULT hr = S_OK;
|
|
WCHAR *pDayString = NULL, *pMonthString = NULL, *pDay = NULL, *pYear = NULL;
|
|
ULONG ulDayLength = 0, ulYearLength = 0;
|
|
long lDayString = -1, lMonthString = -1, lDay = 0, lYear = 0;
|
|
const WCHAR *pStartChar = m_pNextChar, *pEndOfItem = m_pEndOfCurrItem, *pEndChar = m_pEndChar;
|
|
const WCHAR *pTempEndChar = NULL, *pTempEndOfItem = NULL;
|
|
const SPVTEXTFRAG* pFrag = m_pCurrFrag, *pTempFrag = NULL;
|
|
const SPVSTATE *pDayStringXMLState = NULL, *pMonthStringXMLState = NULL, *pDayXMLState = NULL;
|
|
const SPVSTATE *pYearXMLState = NULL;
|
|
CItemList PostDayStringList, PostMonthStringList, PostDayList;
|
|
BOOL fNoYear = false;
|
|
|
|
//--- Try to match Day String
|
|
pDayString = (WCHAR*) pStartChar;
|
|
lDayString = MatchDayString( pDayString, (WCHAR*) pEndOfItem );
|
|
|
|
//--- Failed to match a Day String
|
|
if ( lDayString == 0 )
|
|
{
|
|
pDayString = NULL;
|
|
}
|
|
//--- Matched a Day String, but it wasn't by itself or followed by a comma
|
|
else if ( pDayString != pEndOfItem &&
|
|
( pDayString != pEndOfItem - 1 ||
|
|
*pEndOfItem != L',' ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
//--- Matched a Day String - save XML State and move ahead in text
|
|
else
|
|
{
|
|
pDayString = (WCHAR*) pStartChar;
|
|
pDayStringXMLState = &pFrag->State;
|
|
|
|
pStartChar = pEndOfItem;
|
|
if ( *pStartChar == L',' )
|
|
{
|
|
pStartChar++;
|
|
}
|
|
hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayStringList );
|
|
if ( !pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if ( pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
|
|
}
|
|
}
|
|
|
|
//--- Try to match Day
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
lDay = my_wcstoul( pStartChar, &pDay );
|
|
//--- Matched a Day - save XML State and move ahead in text
|
|
if ( ( DAYMIN <= lDay && lDay <= DAYMAX ) &&
|
|
pDay - pStartChar <= 2 &&
|
|
( pDay == pEndOfItem ||
|
|
( pDay == (pEndOfItem - 1) && *pDay == L',' ) ) )
|
|
{
|
|
if ( pDay == pEndOfItem )
|
|
{
|
|
ulDayLength = (ULONG)(pEndOfItem - pStartChar);
|
|
}
|
|
else if ( pDay == pEndOfItem - 1 )
|
|
{
|
|
ulDayLength = (ULONG)((pEndOfItem - 1) - pStartChar);
|
|
}
|
|
pDay = (WCHAR*) pStartChar;
|
|
pDayXMLState = &pFrag->State;
|
|
|
|
if ( *pEndOfItem == L',' )
|
|
{
|
|
pStartChar = pEndOfItem + 1;
|
|
}
|
|
else
|
|
{
|
|
pStartChar = pEndOfItem;
|
|
}
|
|
|
|
hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostDayList );
|
|
if ( !pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if ( pStartChar &&
|
|
( SUCCEEDED( hr ) ) )
|
|
{
|
|
pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
|
|
//--- Strip trailing punctuation, since the next token will be the last one
|
|
//--- if this is Monthstring, Day, Year
|
|
while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
|
|
{
|
|
if ( *(pEndOfItem - 1) != L',' )
|
|
{
|
|
fNoYear = true;
|
|
}
|
|
pEndOfItem--;
|
|
}
|
|
}
|
|
}
|
|
//--- Failed to match a day
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
//--- Try to match Month String
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pMonthString = (WCHAR*) pStartChar;
|
|
lMonthString = MatchMonthString( pMonthString, (ULONG)(pEndOfItem - pMonthString) );
|
|
|
|
//--- Failed to match Month String, or Month String was not by itself...
|
|
if ( !lMonthString ||
|
|
( pMonthString != pEndOfItem &&
|
|
( pMonthString != pEndOfItem - 1 ||
|
|
*pMonthString != L',' ) ) )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
//--- Matched a Month String - save XML State and move ahead in text
|
|
else
|
|
{
|
|
pMonthString = (WCHAR*) pStartChar;
|
|
pMonthStringXMLState = &pFrag->State;
|
|
|
|
if ( !fNoYear )
|
|
{
|
|
//--- Save pointers, in case there is no year present
|
|
pTempEndChar = pEndChar;
|
|
pTempEndOfItem = pEndOfItem;
|
|
pTempFrag = pFrag;
|
|
|
|
if ( *pEndOfItem == L',' )
|
|
{
|
|
pStartChar = pEndOfItem + 1;
|
|
}
|
|
else
|
|
{
|
|
pStartChar = pEndOfItem;
|
|
}
|
|
|
|
hr = SkipWhiteSpaceAndTags( pStartChar, pEndChar, pFrag, MemoryManager, true, &PostMonthStringList );
|
|
if ( !pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
fNoYear = true;
|
|
pYear = NULL;
|
|
}
|
|
else if ( pStartChar &&
|
|
SUCCEEDED( hr ) )
|
|
{
|
|
pEndOfItem = FindTokenEnd( pStartChar, pEndChar );
|
|
//--- Strip trailing punctuation, etc. since the next token could be the last one if
|
|
//--- this is Day, Monthstring, Year
|
|
while ( IsMiscPunctuation( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsGroupEnding( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsQuotationMark( *(pEndOfItem - 1) ) != eUNMATCHED ||
|
|
IsEOSItem( *(pEndOfItem - 1) ) != eUNMATCHED )
|
|
{
|
|
pEndOfItem--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//--- Try to match Year
|
|
if ( SUCCEEDED( hr ) &&
|
|
!fNoYear )
|
|
{
|
|
lYear = my_wcstoul( pStartChar, &pYear );
|
|
//--- Matched a Year
|
|
if ( ( YEARMIN <= lYear && lYear <= YEARMAX ) &&
|
|
pYear - pStartChar <= 4 &&
|
|
pYear == pEndOfItem )
|
|
{
|
|
//--- Successfully matched Month String, Day, and Year (and possibly Day String)
|
|
pYearXMLState = &pFrag->State;
|
|
ulYearLength = (ULONG)(pEndOfItem - pStartChar);
|
|
pYear = (WCHAR*) pStartChar;
|
|
}
|
|
else
|
|
{
|
|
//--- Failed to match Year - replace pointers with previous values
|
|
pEndChar = pTempEndChar;
|
|
pEndOfItem = pTempEndOfItem;
|
|
pFrag = pTempFrag;
|
|
pYear = NULL;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
TTSWord Word;
|
|
ZeroMemory( &Word, sizeof(TTSWord) );
|
|
Word.eWordPartOfSpeech = MS_Unknown;
|
|
|
|
pItemNormInfo = (TTSItemInfo*) MemoryManager.GetMemory( sizeof(TTSItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
pItemNormInfo->Type = eDATE_LONGFORM;
|
|
|
|
//--- Insert Day String, if present
|
|
if ( pDayString )
|
|
{
|
|
Word.pXmlState = pDayStringXMLState;
|
|
Word.pWordText = g_days[lDayString - 1].pStr;
|
|
Word.ulWordLen = g_days[lDayString - 1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
|
|
//--- Insert Post Day String XML States
|
|
while ( !PostDayStringList.IsEmpty() )
|
|
{
|
|
WordList.AddTail( ( PostDayStringList.RemoveHead() ).Words[0] );
|
|
}
|
|
|
|
//--- Insert Month String
|
|
Word.pXmlState = pMonthStringXMLState;
|
|
Word.pWordText = g_months[lMonthString - 1].pStr;
|
|
Word.ulWordLen = g_months[lMonthString - 1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
|
|
//--- Insert Post Month String XML State
|
|
while ( !PostMonthStringList.IsEmpty() )
|
|
{
|
|
WordList.AddTail( ( PostMonthStringList.RemoveHead() ).Words[0] );
|
|
}
|
|
|
|
SPLISTPOS WordListPos = WordList.GetTailPosition();
|
|
|
|
//--- Expand Day
|
|
if ( ulDayLength == 1 )
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandDigitOrdinal( *pDay, Garbage, WordList );
|
|
}
|
|
else if ( ulDayLength == 2 )
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandTwoOrdinal( pDay, Garbage, WordList );
|
|
}
|
|
|
|
//--- Clean Up Day XML States
|
|
WordList.GetNext( WordListPos );
|
|
while ( WordListPos )
|
|
{
|
|
TTSWord& TempWord = WordList.GetNext( WordListPos );
|
|
TempWord.pXmlState = pDayXMLState;
|
|
}
|
|
|
|
//--- Insert Post Day XML State
|
|
while ( !PostDayList.IsEmpty() )
|
|
{
|
|
WordList.AddTail( ( PostDayList.RemoveHead() ).Words[0] );
|
|
}
|
|
|
|
WordListPos = WordList.GetTailPosition();
|
|
|
|
//--- Expand Year, if present
|
|
if ( pYear )
|
|
{
|
|
TTSYearItemInfo TempYearInfo;
|
|
TempYearInfo.pYear = pYear;
|
|
TempYearInfo.ulNumDigits = ulYearLength;
|
|
hr = ExpandYear( &TempYearInfo, WordList );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
//--- Clean Up Year XML States
|
|
WordList.GetNext( WordListPos );
|
|
while ( WordListPos )
|
|
{
|
|
TTSWord& TempWord = WordList.GetNext( WordListPos );
|
|
TempWord.pXmlState = pYearXMLState;
|
|
}
|
|
}
|
|
}
|
|
//--- Advance pointers
|
|
m_pCurrFrag = pFrag;
|
|
m_pEndChar = pEndChar;
|
|
m_pEndOfCurrItem = pEndOfItem;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
} /* IsLongFormDate_DMDY */
|
|
|
|
/***********************************************************************************************
|
|
* ExpandDate *
|
|
*------------*
|
|
* Description:
|
|
* Expands Items previously determined to be of type Date by IsNumericCompactDate,
|
|
* IsMonthStringCompactDate, or IsTwoValueDate.
|
|
*
|
|
* NOTE: This function does not do parameter validation. Assumed to be done by caller.
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::ExpandDate( TTSDateItemInfo* pItemInfo, CWordList& WordList )
|
|
{
|
|
SPDBG_FUNC( "CStdSentEnum::ExpandDate" );
|
|
HRESULT hr = S_OK;
|
|
TTSWord Word;
|
|
ZeroMemory( &Word, sizeof(TTSWord) );
|
|
Word.pXmlState = &m_pCurrFrag->State;
|
|
Word.eWordPartOfSpeech = MS_Unknown;
|
|
|
|
//--- Insert DayString, if present.
|
|
if ( pItemInfo->ulDayIndex )
|
|
{
|
|
Word.pWordText = g_days[pItemInfo->ulDayIndex - 1].pStr;
|
|
Word.ulWordLen = g_days[pItemInfo->ulDayIndex - 1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
|
|
//--- Insert Month
|
|
Word.pWordText = g_months[pItemInfo->ulMonthIndex - 1].pStr;
|
|
Word.ulWordLen = g_months[pItemInfo->ulMonthIndex - 1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
|
|
//--- Expand Day, if present.
|
|
if ( pItemInfo->pDay )
|
|
{
|
|
if ( pItemInfo->pDay->lLeftOver == 1 )
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandDigitOrdinal( *pItemInfo->pDay->pStartChar, Garbage, WordList );
|
|
}
|
|
else if ( pItemInfo->pDay->lLeftOver == 2 )
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandTwoOrdinal( pItemInfo->pDay->pStartChar, Garbage, WordList );
|
|
}
|
|
}
|
|
|
|
//--- Expand Year, if present.
|
|
if ( pItemInfo->pYear )
|
|
{
|
|
ExpandYear( pItemInfo->pYear, WordList );
|
|
}
|
|
return hr;
|
|
} /* ExpandDate_Standard */
|
|
|
|
/***********************************************************************************************
|
|
* ExpandYear *
|
|
*-------------*
|
|
* Description:
|
|
* Expands four digit strings into words in groups of two, and inserts them into Item List
|
|
* at ListPos. Thus 1999 come out as "nineteen ninety nine" rather than "one thousand nine
|
|
* hundred ninety nine"...
|
|
* Note: This function does not do parameter validation. Assumed to be done by caller.
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::ExpandYear( TTSYearItemInfo* pItemInfo, CWordList& WordList )
|
|
{
|
|
SPDBG_FUNC( "CStdSentEnum::ExpandYear" );
|
|
|
|
// 1000 - 9999
|
|
HRESULT hr = S_OK;
|
|
TTSWord Word;
|
|
ZeroMemory( &Word, sizeof(TTSWord) );
|
|
Word.pXmlState = &m_pCurrFrag->State;
|
|
Word.eWordPartOfSpeech = MS_Unknown;
|
|
NumberGroup Garbage;
|
|
|
|
switch ( pItemInfo->ulNumDigits )
|
|
{
|
|
case 2:
|
|
|
|
//--- Expand as "two thousand" if the two digits are both zeroes.
|
|
if ( pItemInfo->pYear[0] == L'0' &&
|
|
pItemInfo->pYear[1] == L'0' )
|
|
{
|
|
//--- Insert "two".
|
|
Word.pWordText = g_ones[2].pStr;
|
|
Word.ulWordLen = g_ones[2].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
|
|
//--- Insert "thousand".
|
|
Word.pWordText = g_quantifiers[1].pStr;
|
|
Word.ulWordLen = g_quantifiers[1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
//--- Expand as "oh number" if the first digit is zero.
|
|
else if ( pItemInfo->pYear[0] == L'0' )
|
|
{
|
|
Word.pWordText = g_O.pStr;
|
|
Word.ulWordLen = g_O.Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
ExpandDigit( pItemInfo->pYear[1], Garbage, WordList );
|
|
}
|
|
//--- Otherwise just expand as a two digit cardinal number
|
|
else
|
|
{
|
|
ExpandTwoDigits( pItemInfo->pYear, Garbage, WordList );
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
|
|
//--- Expand as a three digit cardinal number;
|
|
ExpandThreeDigits( pItemInfo->pYear, Garbage, WordList );
|
|
break;
|
|
|
|
case 4:
|
|
|
|
//--- If of form "[x]00[y]" expand as "x thousand y", or just "x thousand" if y is also zero.
|
|
if ( pItemInfo->pYear[1] == L'0' &&
|
|
pItemInfo->pYear[2] == L'0' &&
|
|
pItemInfo->pYear[0] != L'0' )
|
|
{
|
|
//--- "x"
|
|
ExpandDigit( pItemInfo->pYear[0], Garbage, WordList );
|
|
|
|
//--- "thousand".
|
|
Word.pWordText = g_quantifiers[1].pStr;
|
|
Word.ulWordLen = g_quantifiers[1].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
|
|
//--- "y"
|
|
if ( pItemInfo->pYear[3] != L'0' )
|
|
{
|
|
ExpandDigit( pItemInfo->pYear[3], Garbage, WordList );
|
|
}
|
|
}
|
|
// Otherwise...
|
|
else
|
|
{
|
|
//--- Expand first two digits - e.g. "nineteen"
|
|
ExpandTwoDigits( pItemInfo->pYear, Garbage, WordList );
|
|
|
|
//--- Expand last two digits - e.g. "nineteen", "hundred", or "oh nine".
|
|
if ( pItemInfo->pYear[2] != '0' )
|
|
{
|
|
//--- the tens is not zero - e.g. 1919 -> "nineteen nineteen"
|
|
ExpandTwoDigits( pItemInfo->pYear + 2, Garbage, WordList );
|
|
}
|
|
else if ( pItemInfo->pYear[3] == '0' )
|
|
{
|
|
//--- tens and ones are both zero - expand as "hundred", e.g. 1900 -> "nineteen hundred"
|
|
Word.pWordText = g_quantifiers[0].pStr;
|
|
Word.ulWordLen = g_quantifiers[0].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
else
|
|
{
|
|
//--- just the tens is zero, expand as "oh x" - e.g. 1909 -> "nineteen oh nine",
|
|
//--- unless both thousands and hundreds were also zero - e.g. 0002 -> "two"
|
|
if ( pItemInfo->pYear[0] != '0' ||
|
|
pItemInfo->pYear[1] != '0' )
|
|
{
|
|
Word.pWordText = g_O.pStr;
|
|
Word.ulWordLen = g_O.Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
|
|
ExpandDigit( pItemInfo->pYear[3], Garbage, WordList );
|
|
}
|
|
}
|
|
}
|
|
return hr;
|
|
} /* ExpandYear */
|
|
|
|
/***********************************************************************************************
|
|
* IsDecade *
|
|
*----------*
|
|
* Description:
|
|
* Checks the incoming Item's text to determine whether or not it
|
|
* is a Decade.
|
|
*
|
|
* RegExp:
|
|
* { ddd0s || d0s || 'd0s || ddd0's || d0's }
|
|
*
|
|
* Types assigned:
|
|
* Decade
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::IsDecade( TTSItemInfo*& pItemNormInfo, CSentItemMemory& MemoryManager )
|
|
{
|
|
SPDBG_FUNC( "CStdSentEnum::IsDecade" );
|
|
|
|
HRESULT hr = S_OK;
|
|
ULONG ulTokenLen = (ULONG)(m_pEndOfCurrItem - m_pNextChar);
|
|
|
|
if ( ulTokenLen < 3 ||
|
|
ulTokenLen > 6 )
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
switch ( ulTokenLen )
|
|
{
|
|
|
|
case 6:
|
|
if ( m_pNextChar[5] == L's' &&
|
|
m_pNextChar[4] == L'\'' &&
|
|
m_pNextChar[3] == L'0' &&
|
|
iswdigit( m_pNextChar[2] ) &&
|
|
iswdigit( m_pNextChar[1] ) &&
|
|
iswdigit( m_pNextChar[0] ) )
|
|
{
|
|
//--- Decade of form ddd0's
|
|
pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
|
|
pItemNormInfo->Type = eDECADE;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = m_pNextChar;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[2] - L'0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
break;
|
|
|
|
case 5:
|
|
if ( m_pNextChar[4] == L's' &&
|
|
m_pNextChar[3] == L'0' &&
|
|
iswdigit( m_pNextChar[2] ) &&
|
|
iswdigit( m_pNextChar[1] ) &&
|
|
iswdigit( m_pNextChar[0] ) )
|
|
{
|
|
//--- Decade of form ddd0s
|
|
pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
|
|
pItemNormInfo->Type = eDECADE;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = m_pNextChar;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[2] - L'0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
if ( m_pNextChar[3] == L's' &&
|
|
m_pNextChar[2] == L'0' &&
|
|
iswdigit( m_pNextChar[1] ) &&
|
|
m_pNextChar[0] == L'\'' )
|
|
{
|
|
//--- Decade of form 'd0s
|
|
pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
|
|
pItemNormInfo->Type = eDECADE;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = NULL;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[1] - L'0';
|
|
}
|
|
}
|
|
else if ( m_pNextChar[3] == L's' &&
|
|
m_pNextChar[2] == L'\'' &&
|
|
m_pNextChar[1] == L'0' &&
|
|
iswdigit( m_pNextChar[0] ) )
|
|
{
|
|
//--- Decade of form d0's
|
|
pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
|
|
pItemNormInfo->Type = eDECADE;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = NULL;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[0] - L'0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
if ( m_pNextChar[2] == L's' &&
|
|
m_pNextChar[1] == L'0' &&
|
|
iswdigit( m_pNextChar[0] ) )
|
|
{
|
|
//--- Decade of form d0s
|
|
pItemNormInfo = (TTSDecadeItemInfo*) MemoryManager.GetMemory( sizeof(TTSDecadeItemInfo), &hr );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
ZeroMemory( pItemNormInfo, sizeof(TTSDecadeItemInfo) );
|
|
pItemNormInfo->Type = eDECADE;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->pCentury = NULL;
|
|
( (TTSDecadeItemInfo*) pItemNormInfo )->ulDecade = m_pNextChar[0] - L'0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
} /* IsDecade */
|
|
|
|
/***********************************************************************************************
|
|
* ExpandDecade *
|
|
*--------------*
|
|
* Description:
|
|
* Expands Items previously determined to be of type Decade by IsDecade.
|
|
*
|
|
* NOTE: This function does not do parameter validation. Assumed to be done by caller.
|
|
********************************************************************* AH **********************/
|
|
HRESULT CStdSentEnum::ExpandDecade( TTSDecadeItemInfo* pItemInfo, CWordList& WordList )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fDone = false;
|
|
TTSWord Word;
|
|
ZeroMemory( &Word, sizeof(TTSWord) );
|
|
Word.pXmlState = &m_pCurrFrag->State;
|
|
Word.eWordPartOfSpeech = MS_Unknown;
|
|
|
|
//--- Four digit form
|
|
if ( pItemInfo->pCentury )
|
|
{
|
|
//--- Cover special cases first
|
|
|
|
//--- 00dds
|
|
if ( pItemInfo->pCentury[0] == '0' &&
|
|
pItemInfo->pCentury[1] == '0' )
|
|
{
|
|
//--- 0000s - expand as "zeroes"
|
|
if ( pItemInfo->ulDecade == 0 )
|
|
{
|
|
Word.pWordText = g_Zeroes.pStr;
|
|
Word.ulWordLen = g_Zeroes.Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
fDone = true;
|
|
}
|
|
//--- 00d0s
|
|
else
|
|
{
|
|
// Just expand the decade part as we normally would
|
|
NULL;
|
|
}
|
|
}
|
|
//--- 0dd0s - expand as "d hundreds" or "d hundred [decade part]"
|
|
else if ( pItemInfo->pCentury[0] == '0' )
|
|
{
|
|
//--- insert first digit
|
|
Word.pWordText = g_ones[ pItemInfo->pCentury[0] - L'0' ].pStr;
|
|
Word.ulWordLen = g_ones[ pItemInfo->pCentury[0] - L'0' ].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
|
|
//--- 0d00s - expand as "d hundreds"
|
|
if ( SUCCEEDED( hr ) &&
|
|
pItemInfo->ulDecade == 0 )
|
|
{
|
|
Word.pWordText = g_Hundreds.pStr;
|
|
Word.ulWordLen = g_Hundreds.Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
fDone = true;
|
|
}
|
|
//--- 0dd0s - expand as "d hundred [decade part]"
|
|
else if ( SUCCEEDED( hr ) )
|
|
{
|
|
Word.pWordText = g_hundred.pStr;
|
|
Word.ulWordLen = g_hundred.Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
}
|
|
//--- d000s, dd00s - expand as "d thousands" or "dd hundreds"
|
|
else if ( pItemInfo->ulDecade == 0 )
|
|
{
|
|
//--- d000s - "d thousands" ( "thousands" will get inserted below )
|
|
if ( pItemInfo->pCentury[1] == '0' )
|
|
{
|
|
Word.pWordText = g_ones[ pItemInfo->pCentury[0] - L'0' ].pStr;
|
|
Word.ulWordLen = g_ones[ pItemInfo->pCentury[0] - L'0' ].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
//--- dd00s - "dd hundreds"
|
|
else
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandTwoDigits( pItemInfo->pCentury, Garbage, WordList );
|
|
|
|
Word.pWordText = g_Hundreds.pStr;
|
|
Word.ulWordLen = g_Hundreds.Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
fDone = true;
|
|
}
|
|
}
|
|
//--- Default case: ddd0s - expand as "dd [decade part]"
|
|
else
|
|
{
|
|
NumberGroup Garbage;
|
|
ExpandTwoDigits( pItemInfo->pCentury, Garbage, WordList );
|
|
}
|
|
}
|
|
//--- Special case - 00s should expand as "two thousands"
|
|
else if ( pItemInfo->ulDecade == 0 )
|
|
{
|
|
Word.pWordText = g_ones[2].pStr;
|
|
Word.ulWordLen = g_ones[2].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
|
|
//--- Expand decade part, if necessary
|
|
if ( SUCCEEDED(hr) &&
|
|
!fDone )
|
|
{
|
|
Word.pWordText = g_Decades[ pItemInfo->ulDecade ].pStr;
|
|
Word.ulWordLen = g_Decades[ pItemInfo->ulDecade ].Len;
|
|
Word.pLemma = Word.pWordText;
|
|
Word.ulLemmaLen = Word.ulWordLen;
|
|
WordList.AddTail( Word );
|
|
}
|
|
|
|
return hr;
|
|
} /* ExpandDecade */
|
|
|
|
/***********************************************************************************************
|
|
* MatchMonthString *
|
|
*------------------*
|
|
* Description:
|
|
* This is just a helper function - it returns the integer value of the month found in
|
|
* its WCHAR string parameter ("January" is 1, "February" 2, etc.) or zero if it finds no match.
|
|
* It also checks three letter abbreviations - "Jan", "Feb", etc.
|
|
* Note: This function does not do parameter validation. Assumed to be done by caller
|
|
* (GetNumber should be called first to get the NumberInfo structure and valiDate parameters).
|
|
********************************************************************* AH **********************/
|
|
ULONG CStdSentEnum::MatchMonthString( WCHAR*& pMonth, ULONG ulLength )
|
|
{
|
|
ULONG ulMonth = 0;
|
|
|
|
//--- Check full months strings
|
|
for ( int i = 0; i < sp_countof(g_months); i++ )
|
|
{
|
|
if ( ulLength >= (ULONG) g_months[i].Len &&
|
|
wcsnicmp( pMonth, g_months[i].pStr, g_months[i].Len ) == 0 )
|
|
{
|
|
ulMonth = i + 1;
|
|
pMonth = pMonth + g_months[i].Len;
|
|
break;
|
|
}
|
|
}
|
|
//--- Check month abbreviations
|
|
if ( !ulMonth )
|
|
{
|
|
for ( i = 0; i < sp_countof(g_monthAbbreviations); i++ )
|
|
{
|
|
if ( ulLength >= (ULONG) g_monthAbbreviations[i].Len &&
|
|
wcsnicmp( pMonth, g_monthAbbreviations[i].pStr, g_monthAbbreviations[i].Len ) == 0 )
|
|
{
|
|
if ( i > 8 )
|
|
{
|
|
ulMonth = i;
|
|
}
|
|
else
|
|
{
|
|
ulMonth = i + 1;
|
|
}
|
|
pMonth = pMonth + g_monthAbbreviations[i].Len;
|
|
if ( *pMonth == L'.' )
|
|
{
|
|
pMonth++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ulMonth;
|
|
} /* MatchMonthString */
|
|
|
|
/***********************************************************************************************
|
|
* MatchDayString *
|
|
*----------------*
|
|
* Description:
|
|
* This is just a helper function - it returns the integer value of the day found in
|
|
* its WCHAR string parameter ("Monday" is 0, "Tuesday" 1, etc.) or -1 if it finds no match.
|
|
* It also checks abbreviations - "Mon", "Tue", etc.
|
|
* Note: This function does not do parameter validation. Assumed to be done by caller
|
|
********************************************************************* AH **********************/
|
|
ULONG CStdSentEnum::MatchDayString( WCHAR*& pDayString, WCHAR* pEndChar )
|
|
{
|
|
ULONG ulDay = 0;
|
|
|
|
//--- Check full day strings
|
|
for ( int i = 0; i < sp_countof(g_days); i++ )
|
|
{
|
|
if ( pEndChar - pDayString >= g_days[i].Len &&
|
|
wcsnicmp( pDayString, g_days[i].pStr, g_days[i].Len ) == 0 )
|
|
{
|
|
ulDay = i + 1;
|
|
pDayString = pDayString + g_days[i].Len;
|
|
break;
|
|
}
|
|
}
|
|
//--- Check month abbreviations
|
|
if ( !ulDay )
|
|
{
|
|
for ( i = 0; i < sp_countof(g_dayAbbreviations); i++ )
|
|
{
|
|
if ( pEndChar - pDayString >= g_dayAbbreviations[i].Len &&
|
|
wcsncmp( pDayString, g_dayAbbreviations[i].pStr, g_dayAbbreviations[i].Len ) == 0 )
|
|
{
|
|
switch (i)
|
|
{
|
|
//--- Mon, Tues
|
|
case 0:
|
|
case 1:
|
|
ulDay = i + 1;
|
|
break;
|
|
//--- Tue, Wed, Thurs
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
ulDay = i;
|
|
break;
|
|
//--- Thur, Thu
|
|
case 5:
|
|
case 6:
|
|
ulDay = 4;
|
|
break;
|
|
//--- Fri, Sat, Sun
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
ulDay = i - 2;
|
|
break;
|
|
}
|
|
|
|
pDayString = pDayString + g_dayAbbreviations[i].Len;
|
|
if ( *pDayString == L'.' )
|
|
{
|
|
pDayString++;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ulDay;
|
|
} /* MatchDayString */
|
|
|
|
/***********************************************************************************************
|
|
* MatchDateDelimiter *
|
|
*--------------------*
|
|
* Description:
|
|
* This is just a helper function - it returns true or false based on whether the first
|
|
* character in its parameter string is a valid Date Delimiter. It also advances its parameter
|
|
* string pointer one position (past the Date Delimiter) and replaces a valid delimiter with
|
|
* a null terminator.
|
|
* Note: This function does not do parameter validation. Assumed to be done by caller
|
|
* (GetNumber should be called first to get the NumberInfo structure and valiDate parameters).
|
|
********************************************************************* AH **********************/
|
|
bool CStdSentEnum::MatchDateDelimiter( WCHAR** DateString )
|
|
{
|
|
bool bIsDelimiter = false;
|
|
|
|
if (DateString)
|
|
{
|
|
for (int i = 0; i < sp_countof(g_DateDelimiters); i++)
|
|
{
|
|
if (*DateString[0] == g_DateDelimiters[i])
|
|
{
|
|
bIsDelimiter = true;
|
|
*DateString = *DateString + 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bIsDelimiter;
|
|
} /* MatchDateDelimiter */
|
|
|
|
//------------End Of File-----------------------------------------------------------------------------
|