diff -r 000000000000 -r f979ecb2b13e pimappsupport/vcardandvcal/src/VRECUR.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pimappsupport/vcardandvcal/src/VRECUR.CPP Tue Feb 02 10:12:19 2010 +0200 @@ -0,0 +1,1123 @@ +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include "verror.h" +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS +#include "versit_internal.h" +#endif +// +// CWeekDayArray +// + +EXPORT_C CWeekDayArray::CWeekDayArray() +: iArray(NULL) +/** Constructs an array of the days in the week. */ + {} + +EXPORT_C CWeekDayArray::~CWeekDayArray() +/** Frees all resources owned by the object, prior to its destruction. */ + { + delete iArray; + } + +EXPORT_C void CWeekDayArray::ExternalizeL(RWriteStream& aStream) +/** Externalises the array of days in the week to a write stream. + +Writes the first two characters of each day name, for instance "MO TU WE". + +The presence of this function means that the standard templated operator<<() +(defined in s32strm.h) is available to externalise objects of this class. + +@param aStream Stream to which the array is to be externalised. */ + { + if (iArray) + { + TInt count=iArray->Count(); + for (TInt ii=0; iiExternalizeL(aStream); + } + +// +// CVersitRecurrenceMonthlyByPos +// + +EXPORT_C CVersitRecurrenceMonthlyByPos::CVersitRecurrenceMonthlyByPos(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,CArrayPtrFlat* aMonthPositions) +: CVersitRecurrence(aInterval,aDuration,aEndDate) +,iMonthPositions(aMonthPositions) +/** Constructs the CVersitRecurrenceMonthlyByPos object. + +Sets the interval, the duration, optionally, an end date for the repeat and +a pointer to an array of 'month positions', which specify when the event occurs. +Also sets the repeat type to EMonthlyByPos. + +If a duration and an end date are both specified, the end date takes precedence. + +@param aInterval The number of months between repeats. +@param aDuration The duration, in months, for which the event should recur. +A value of zero indicates the repeat should continue forever. +@param aEndDate Pointer to the end date for the repeat event. The object takes +ownership of this pointer. +@param aMonthPositions Pointer to an array of the positions of days within +the month. The object takes ownership of this pointer. */ + { + iRepeatType=EMonthlyByPos; + } + +EXPORT_C CVersitRecurrenceMonthlyByPos::~CVersitRecurrenceMonthlyByPos() +/** Frees all resources owned by the object, prior to its destruction. */ + { + if (iMonthPositions) + { + iMonthPositions->ResetAndDestroy(); + delete iMonthPositions; + } + } + +EXPORT_C void CVersitRecurrenceMonthlyByPos::ExternalizeOccurrenceListsL(RWriteStream& aStream) const +/** Writes the days of the month on which the event occurs to the output stream, +aStream. + +If an event occurs on Monday and Tuesday of the first week and the second to last week +of a month, the string written to aStream would be "1+ MO TU 2- MO TU ", with +the plus sign indicating that the week is counted from the start of the month +and the minus sign indicating that the week is counted from the end of the +month. + +@param aStream The stream to which the occurrence list is to be written. */ + { + if (iMonthPositions) + { + const TInt count = iMonthPositions->Count(); + CMonthPosition* monthPos; + TBuf8<1> weekNo; + for (TInt ii = 0; ii < count; ii++) + { + monthPos = (*iMonthPositions)[ii]; + __ASSERT_DEBUG((monthPos->iWeekNo < 10), Panic(EWeekNoOverTen)); + weekNo.Num(monthPos->iWeekNo); + aStream.WriteL(weekNo); + if (monthPos->iSign == CMonthPosition::EWeeksFromEndOfMonth) + aStream.WriteL(KVersitTokenMinus); + else + aStream.WriteL(KVersitTokenPlus); + aStream.WriteL(KVersitTokenSpace); + if (monthPos->iArrayOfWeekDays) + monthPos->iArrayOfWeekDays->ExternalizeL(aStream); + } + } + } + +EXPORT_C CVersitRecurrenceMonthlyByPos::CMonthPosition::~CMonthPosition() +/** Frees all resources owned by the object, prior to its destruction. */ + { + delete iArrayOfWeekDays; + } + +// +// CVersitRecurrenceMonthlyByDay +// +EXPORT_C CVersitRecurrenceMonthlyByDay::CVersitRecurrenceMonthlyByDay(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate, CArrayFix* aArrayOfOccurrencesInDaysFromStartOfMonth + ,CArrayFix* aArrayOfOccurrencesInDaysFromEndOfMonth,TBool aLastDay) +: CVersitRecurrence(aInterval,aDuration,aEndDate) +,iArrayOfOccurrencesInDaysFromStartOfMonth(aArrayOfOccurrencesInDaysFromStartOfMonth) +,iArrayOfOccurrencesInDaysFromEndOfMonth(aArrayOfOccurrencesInDaysFromEndOfMonth) +,iLastDay(aLastDay) +/** Constructs the CVersitRecurrenceMonthlyByDay object. + +Sets the repeat type to CVersitRecurrence::EMonthlyByDay. Note: if a duration and an end +date are both specified, the end date takes precedence. + +@param aInterval The number of months between repeats. +@param aDuration The duration, in months, for which the event should recur. +A value of zero indicates the repeat should continue forever. +@param aEndDate Optional pointer to the end date for the repeat event. The object +takes ownership of this pointer. +@param aArrayOfOccurencesInDaysFromStartOfMonth Optional pointer to an array of +numbers, each of which can have a value between 1 and 31 inclusive, which identify +the days, counting from the start of the month, on which the repeat event occurs. The +object takes ownership of this pointer. +@param aArrayOfOccurrencesInDaysFromEndOfMonth Optional pointer to an array of numbers, +each of which can have a value between 1 and 31 inclusive, which identify the days, +counting from the end of the month, on which the repeat event occurs. (The last day of +the month is represented by 1). The object takes ownership of this pointer. +@param aLastDay Optional - ETrue if the event occurs on the last day of the month. This +day can then be represented in the output stream using the LD recurrence value. EFalse if not. */ + { + iRepeatType=EMonthlyByDay; + } + +EXPORT_C CVersitRecurrenceMonthlyByDay::~CVersitRecurrenceMonthlyByDay() +/** Frees all resources owned by the object, prior to its destruction. */ + { + delete iArrayOfOccurrencesInDaysFromStartOfMonth; + delete iArrayOfOccurrencesInDaysFromEndOfMonth; + } + +EXPORT_C void CVersitRecurrenceMonthlyByDay::ExternalizeOccurrenceListsL(RWriteStream& aStream) const +/** Writes the days of the month on which the event occurs to the output stream, +aStream. + +For days counted from the beginning of the month, the string written to aStream +might be "1+ 2+ 16+ 17+ ", with the plus sign indicating that the day is counted +from the start of the month. + +For days counted from the end of the month, the string written to aStream +might be "1- 3- 4- LD ", with "LD" signifying that the event occurs on the +last day of the month. + +@param aStream The stream to which the occurrence list is to be written. */ + { + if (iArrayOfOccurrencesInDaysFromStartOfMonth) + { + TInt count = iArrayOfOccurrencesInDaysFromStartOfMonth->Count(); + TInt occurrence; + TBuf8 temp; + for (TInt ii = 0; ii < count; ii++) + { + occurrence = (*iArrayOfOccurrencesInDaysFromStartOfMonth)[ii]; + if ((occurrence < 32) && (occurrence > 0)) //day in month + { + temp.Num(occurrence); + aStream.WriteL(temp); + aStream.WriteL(KVersitTokenPlus); + aStream.WriteL(KVersitTokenSpace); + } + } + } + if (iArrayOfOccurrencesInDaysFromEndOfMonth) + { + TInt count = iArrayOfOccurrencesInDaysFromEndOfMonth->Count(); + TInt occurrence; + TBuf8 temp; + for (TInt ii = 0; ii < count; ii++) + { + occurrence = (*iArrayOfOccurrencesInDaysFromEndOfMonth)[ii]; + if ((occurrence < 32) && (occurrence > 0)) //day in month + { + temp.Num(occurrence); + aStream.WriteL(temp); + aStream.WriteL(KVersitTokenMinus); + aStream.WriteL(KVersitTokenSpace); + } + } + } + if (iLastDay) + { + aStream.WriteL(KVersitRecurrenceLastDay); + aStream.WriteL(KVersitTokenSpace); + } + } + +// +// CVersitRecurrenceYearlyByMonth +// + +EXPORT_C CVersitRecurrenceYearlyByMonth::CVersitRecurrenceYearlyByMonth(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,CArrayFix* aArrayOfMonthsInYearOccurrences) +: CVersitRecurrence(aInterval,aDuration,aEndDate) +, iArrayOfMonthsInYearOccurrences(aArrayOfMonthsInYearOccurrences) +/** Constructs the CVersitRecurrenceYearlyByMonth object. + +Sets the repeat type to CVersitRecurrence::EYearlyByMonth. + +If a duration and an end date are both specified, the end date takes precedence. + +@param aInterval The number of years between repeats. +@param aDuration The duration, in years, for which the event should recur. +A value of zero indicates the repeat should continue forever. +@param aEndDate Optional pointer to the end date for the repeat event. The object takes +ownership of this pointer. +@param aArrayOfMonthsInYearOccurrences Pointer to an array of month values. +The object takes ownership of this pointer. */ + { + iRepeatType=EYearlyByMonth; + } + +EXPORT_C CVersitRecurrenceYearlyByMonth::~CVersitRecurrenceYearlyByMonth() +/** Frees all resources owned by the object, prior to its destruction. */ + { + delete iArrayOfMonthsInYearOccurrences; + } + +EXPORT_C void CVersitRecurrenceYearlyByMonth::ExternalizeOccurrenceListsL(RWriteStream& aStream) const +/** Writes the months of the year, as month numbers, in which the event occurs to +the output stream. + +For example, if the event occurs from September to December inclusive, the +string written to aStream would be "9 10 11 12 ". + +@param aStream The stream to which the occurrence list is to be written. */ + { + if (iArrayOfMonthsInYearOccurrences) + { + TInt count = iArrayOfMonthsInYearOccurrences->Count(); + TBuf8 temp; + for (TInt ii = 0; ii < count; ii++) + { + temp.Num((*iArrayOfMonthsInYearOccurrences)[ii] + 1); // Add 1 since EJanuary = 0, not 1 + aStream.WriteL(temp); + aStream.WriteL(KVersitTokenSpace); + } + } + } + +// +// CVersitRecurrenceYearlyByDay +// +EXPORT_C CVersitRecurrenceYearlyByDay::CVersitRecurrenceYearlyByDay(TInt aInterval,TInt aDuration,TVersitDateTime* aEndDate,CArrayFix* aArrayOfDaysInYearOccurrences) +: CVersitRecurrence(aInterval,aDuration,aEndDate) +,iArrayOfDaysInYearOccurrences(aArrayOfDaysInYearOccurrences) +/** Constructs the CVersitRecurrenceYearlyByDay object. + +Sets the repeat type to EYearlyByDay. + +If a duration and an end date are both specified, the end date takes precedence. + +@param aInterval The number of years between repeats. +@param aDuration The duration, in years, for which the event should +recur. A value of zero indicates the repeat should continue forever. +@param aEndDate Optional pointer to the end date for the repeat event. The object takes +ownership of this pointer. +@param aArrayOfDaysInYearOccurrences Pointer to an array of integers between +1 and 366 inclusive. Each integer represents a day on which the repeat event +occurs. The object takes ownership of this pointer. */ + { + iRepeatType=EYearlyByDay; + } + +EXPORT_C CVersitRecurrenceYearlyByDay::~CVersitRecurrenceYearlyByDay() +/** Frees all resources owned by the object, prior to its destruction. */ + { + delete iArrayOfDaysInYearOccurrences; + } + +EXPORT_C void CVersitRecurrenceYearlyByDay::ExternalizeOccurrenceListsL(RWriteStream& aStream) const +/** Writes the days of the year on which the event occurs to the output stream, +aStream. + +For example, the function might write the string "10 11 12 13 14 15 ". + +@param aStream The stream to which the occurrence list is to be written. */ + { + if (iArrayOfDaysInYearOccurrences) + { + TInt count=iArrayOfDaysInYearOccurrences->Count(); + TInt occurrence; + TBuf8 temp; + for (TInt ii = 0; ii < count; ii++) + { + occurrence = (*iArrayOfDaysInYearOccurrences)[ii]; + temp.Num(occurrence); + if ((occurrence < 366) && (occurrence > 0)) //day in year + { + aStream.WriteL(temp); + aStream.WriteL(KVersitTokenSpace); + } + } + } + } + +// +// CParserPropertyValueRecurrence +// +EXPORT_C CParserPropertyValueRecurrence::CParserPropertyValueRecurrence(CVersitRecurrence* aValue) +: CParserTimePropertyValue(TUid::Uid(KVCalPropertyRecurrenceUid)) +, iValue(aValue) +/** Constructs a recurrence property value. + +Sets the property value's UID to KVCalPropertyRecurrenceUid. + +@param aValue A pointer to the recurrence value to assign to the property +value parser. The property value parser takes ownership of the pointer. */ + {} + +EXPORT_C CParserPropertyValueRecurrence::~CParserPropertyValueRecurrence() +/** Frees all resources owned by the property value, prior to its destruction. */ + { + delete iValue; + } + +EXPORT_C void CParserPropertyValueRecurrence::ConvertAllDateTimesToUTCL(const TTimeIntervalSeconds& /*aIncrement*/,const CVersitDaylight* /*aDaylight*/) +/** Converts the end time of the recurrence value into universal time. + +The date/time is checked against the daylight saving information provided +in aDaylight. If it falls inside the daylight saving period then the daylight +saving offset is subtracted from the time to convert it to universal time. +Otherwise the time is modified by aIncrement to convert it to universal time. + +Note that the daylight savings offset will adjust the time both for the daylight +saving and for the time zone. + +The function has no effect if the value is already stored in universal time. + +If aDaylight is a NULL pointer then aIncrement is used. + +@param aIncrement A time interval in seconds which represents the negative +of the time zone of the originating machine. For instance, if the time zone +is +04:30 (that is 4hr 30mins ahead of UTC), aIncrement should be set to minus +the number of seconds in 4hr 30mins.. +@param aDaylight Pointer to the specification for daylight saving. If the date/time +value is within the period for daylight saving, the value is modified by the +daylight saving offset (which accounts for both the time zone and daylight +saving rule). +@deprecated since 9.1 +*/ + { + } + +EXPORT_C void CParserPropertyValueRecurrence::ConvertAllUTCDateTimesToMachineLocalL(const TTimeIntervalSeconds& /*aIncrement*/) +/** Converts the end time of the recurrence value into machine-local time. + +This process involves adjusting the date/time value by the offset in aIncrement. + +The function has no effect if the value is already stored in machine-local +time. + +@param aIncrement A time interval which represents the number of seconds which +is to be added to the date/time value. This should normally be the universal +time offset for the machine's locale. +@deprecated since 9.1 +*/ + { + } + +EXPORT_C void CParserPropertyValueRecurrence::ExternalizeL(RWriteStream& aStream,const Versit::TEncodingAndCharset& /*aEncodingCharset*/ + ,TInt /*aLengthOutput*/) +/** Externalises the recurrence property value into aStream. + +The property is written to the stream in the following order: + +- Repeat type, e.g. "D" is written for a daily repeat (see KVersitRecurrenceDaily). + +- Repeat interval, e.g. "2" for a weekly repeat type that occurs fortnightly. + +- Occurrence list (optional), e.g. the string "MO TH" is written for a weekly repeat type that recurs +on Mondays and Thursdays. + +- End date (optional) - the date on which the event should stop recurring. + +- Duration, e.g. "#10" for a weekly repeat type that should last for 10 weeks. + +For example, "W2 TU TH #10", means a repeat every second Tuesday and Thursday for 10 weeks + +@param aStream Stream to which the value is to be externalised. +@param aEncodingCharset Specifies character set and encoding information. This is not +used by this function since the recurrence rule value is in ASCII. +@param aLengthOutput The amount of text that has been output so far on the line. This is not used by +this function since the line wrapping is not a general case for recurrence values. */ + { + if (!iValue) + return; + switch(iValue->iRepeatType) + { + case CVersitRecurrence::EDaily: + aStream.WriteL(KVersitRecurrenceDaily); + break; + case CVersitRecurrence::EWeekly: + aStream.WriteL(KVersitRecurrenceWeekly); + break; + case CVersitRecurrence::EMonthlyByPos: + aStream.WriteL(KVersitRecurrenceMonthlyByPos8); + break; + case CVersitRecurrence::EMonthlyByDay: + aStream.WriteL(KVersitRecurrenceMonthlyByDay8); + break; + case CVersitRecurrence::EYearlyByMonth: + aStream.WriteL(KVersitRecurrenceYearlyByMonth8); + break; + case CVersitRecurrence::EYearlyByDay: + aStream.WriteL(KVersitRecurrenceYearlyByDay8); + break; + default: + Panic(ENoRecognizedRepeatType); + break; + }; + TBuf8 temp; + temp.Num(iValue->iInterval); + aStream.WriteL(temp); + aStream.WriteL(KVersitTokenSpace); + iValue->ExternalizeOccurrenceListsL(aStream); + if (iValue->iEndDate) + { + TBuf8 buf; + EncodeVersitDateTimeL(buf,*iValue->iEndDate); + aStream.WriteL(buf); + } + else + { + aStream.WriteL(KVersitRecurrenceNumberOf); + temp.Num(iValue->iDuration); + aStream.WriteL(temp); + } + } + +// +// CRecurrenceParser +// +EXPORT_C CRecurrenceParser::CRecurrenceParser(TBool aHasVersion) + : CVersitParser(aHasVersion) //(aHasVersion? ESupportsVersion:ENoVersionProperty) +/** Constructs a recurrence parser. + +@param aHasVersion CVersitParser::ESupportsVersion if a version property is needed; +ENoVersionProperty otherwise. */ + {} + +EXPORT_C CParserPropertyValue* CRecurrenceParser::MakePropertyValueRecurrenceL(TDes& aRecurringEntity) +/** Internalises a recurrence property value in descriptor form. + +Creates a recurrence parser using the recurrence information provided in aRecurringEntity +(which has the format described in CParserPropertyValueRecurrence::ExternalizeL()). + +@param aRecurringEntity A recurring entity in descriptor form. */ + { + aRecurringEntity.TrimAll(); + if(aRecurringEntity.Length()==0) + { + CParserPropertyValue* value = new(ELeave) CParserPropertyValueRecurrence(NULL); + return value; + } + + // if there is no space between Event's interval (e.g. D1) and occurrence (e.g. #2), + // i.e. for e.g. D1#2 then leave + TInt posSpace=aRecurringEntity.Locate(ESpace); + TInt posNumSign=aRecurringEntity.Locate(KVersitRecurrenceNumberOfVal); + if(posSpace==KErrNotFound && posNumSign!=KErrNotFound) + { + User::Leave(KVersitErrBadRepeatValue); + } + //Extract the first part - Recurrence Type + TPtrC recurrEntity(aRecurringEntity); + TPtrC recurrenceType; + if(posSpace==KErrNotFound) + { + recurrenceType.Set(recurrEntity.Left(aRecurringEntity.Length())); + } + else + { + recurrenceType.Set(recurrEntity.Left(posSpace)); + } + + if(recurrenceType.Length()<2) + { + // Only one letter for iRecurrenceType is not acceptable. + User::Leave(KVersitErrBadRepeatValue); + } + + // if occurrence is not specified i.e. only D specified, not D # + // then by vcal specification default occurrence value should be 2 + TInt len=aRecurringEntity.Length()-posSpace-1; + _LIT(KVersitRecurrenceDefVal, "#2"); + TPtr restString((TPtr &)KVersitRecurrenceDefVal); + + //if occurrence is specified the extract from Recurring Rule + if(posSpace!=KErrNotFound) + { + restString.Set(&aRecurringEntity[posSpace+1],len,len); + } + + posSpace=restString.LocateReverse(ESpace); + TBool dateTimeAtEnd=EFalse; + TBool numCurrenceAtEnd=EFalse; + TBool thereIsADateList=ETrue; + len=restString.Length()-posSpace-1; + TPtr dateTime(&restString[posSpace+1],len,len); + if(dateTime.Length()>14) + { + dateTimeAtEnd=ETrue; + if (posSpace==KErrNotFound) + restString.Set(NULL,0,0); + else + restString.Set(&restString[0],posSpace,posSpace); + } + else + { + //Ensure that dateTime is a time parameter, and not a weekday. + //This is true if the sequence length is greater than two + //characters, and the sequence begins with 'T' + TInt posTimeDelimeter=dateTime.Locate(KVersitTimePeriodTimeVal); + if(posTimeDelimeter == 0 && dateTime.Length() > 2) + { + //we want to strip off this date from + if(posSpace==KErrNotFound) + restString.Set(NULL,0,0); + else + restString.Set(&restString[0],posSpace,posSpace); + } + } + TPtrC numCurrence; + TPtrC dateList;//use null string + if (restString.Length()>0) + { + posSpace=restString.Locate(KVersitRecurrenceNumberOfVal); + if(posSpace >= 0) + { + numCurrenceAtEnd=ETrue; + if(posSpace>restString.Length()-2) + User::Leave(KVersitErrBadRepeatValue); + numCurrence.Set(restString.Mid(posSpace+1)); + } + if(posSpace > 1) + { + len=posSpace-1; + restString.Set(&restString[0],len,len);//there is space before '#' + } + else + thereIsADateList=(posSpace==KErrNotFound); + } + else + thereIsADateList=EFalse; + if(thereIsADateList) + { + dateList.Set(restString); + } + CVersitRecurrence::TType repeatType; + TInt interval; + GetFrequencyAndIntervalL(repeatType,interval,recurrenceType);//parse first part, such as W2,D1,YM1... + CVersitRecurrence* recurrence = GetFrequencyModifiersL(repeatType,interval,dateList/*dateListConcatenated*/);//parse the second part such as "1TH TU 2 WE" + CleanupStack::PushL(recurrence); + + // set duration and enddate values + if(numCurrenceAtEnd) + { + TInt numChar; + recurrence->iDuration = GetNumberL(numCurrence,numChar); + } + if(dateTimeAtEnd) + // Coverity doesn't acknowledge member assignment as leave safe + // coverity[alloc_fn] coverity[assign] + recurrence->iEndDate=DecodeDateTimeL(dateTime); + + // no duration (#n) and no end date implies duration = #2 + if ( !(numCurrenceAtEnd || dateTimeAtEnd) ) + { + recurrence->iDuration = 2; + } + + // coverity[leave_without_push] + CParserPropertyValue* value = new(ELeave) CParserPropertyValueRecurrence(recurrence); + CleanupStack::Pop(recurrence); + return value; + } + +void CRecurrenceParser::ResetAndDestroyArrayOfMonthPositions(TAny* aObject) + { + CArrayPtr* array=REINTERPRET_CAST(CArrayPtr*,aObject); + if (array) + array->ResetAndDestroy(); + delete array; + } + +// For interoperability with Nokia 9110's incorrectly specified +// vCalendar repeat rules a check is made after matching a 'M' or 'Y' +// character that the next character isn't the repeat interval. See +// defects EDNCDUG-4FXPKP and EDNCDUG-4FXRAA (Symbian defect tracking v3) +// for more detail. +// +void CRecurrenceParser::GetFrequencyAndIntervalL(CVersitRecurrence::TType& aFrequency,TInt& aInterval, const TDesC& aRecurrenceType) + { + TInt position = 0; + const TUint type = aRecurrenceType[position]; + TPtrC recMonthlyByPos(KVersitRecurrenceMonthlyByPos);//MP + TPtrC recYearlyByDay(KVersitRecurrenceYearlyByDay);//YD + if (type == KVersitRecurrenceDailyVal) + { + position++; + aFrequency = CVersitRecurrence::EDaily; + } + else if (type == KVersitRecurrenceWeeklyVal) + { + position++; + aFrequency = CVersitRecurrence::EWeekly; + } + else if (type == recMonthlyByPos[0]) + { + position++; + if (aRecurrenceType[position] == recMonthlyByPos[position]) + aFrequency = CVersitRecurrence::EMonthlyByPos; + else + aFrequency = CVersitRecurrence::EMonthlyByDay; + TChar nextChar = aRecurrenceType[position]; + if (!nextChar.IsDigit()) + position++; + } + else if (type == recYearlyByDay[0]) + { + position++; + if (aRecurrenceType[position] == recYearlyByDay[position]) + aFrequency = CVersitRecurrence::EYearlyByDay; + else + aFrequency = CVersitRecurrence::EYearlyByMonth; + TChar nextChar = aRecurrenceType[position]; + if (!nextChar.IsDigit()) + position++; + } + else + User::Leave(KVersitErrRepeatTypeNotHandled); + TInt numChars; + aInterval = GetNumberL(aRecurrenceType.Mid(position),numChars); + } + +CVersitRecurrence* CRecurrenceParser::GetFrequencyModifiersL(const CVersitRecurrence::TType& aRepeatType,TInt aInterval, const TDesC& aListDates) + { + CVersitRecurrence* recurrence = NULL; + switch (aRepeatType) + { + case CVersitRecurrence::EDaily: + recurrence = new(ELeave)CVersitRecurrenceDaily(aInterval, 0, 0); + break; + case CVersitRecurrence::EWeekly: + { + CWeekDayArray* weekDays=GetListOfWeekDayOccurrencesL(aListDates); + CleanupStack::PushL(weekDays); + recurrence = new(ELeave)CVersitRecurrenceWeekly(aInterval, 0, 0, weekDays); + CleanupStack::Pop(weekDays); + } + break; + case CVersitRecurrence::EMonthlyByPos: + { + CArrayPtrFlat* monthPositions + = new(ELeave) CArrayPtrFlat(5); + CleanupStack::PushL(TCleanupItem(ResetAndDestroyArrayOfMonthPositions, monthPositions)); + CPtrCArray* array =new(ELeave)CPtrC16Array(5);//each of them is something like "1 TH TU" + CleanupStack::PushL(array);// + TInt i; + TInt lastDigitPos=0; + TInt length=aListDates.Length(); + if (length>0) + { + for(i=1;iAppendL(aListDates.Mid(lastDigitPos,i-lastDigitPos)); + lastDigitPos=i; + } + } + if(lastDigitPos!=length-1) + array->AppendL(aListDates.Mid(lastDigitPos)); + } + TInt count=array->Count(); + for(i=0;iiSign=CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromEndOfMonth; + else + newMonthPosition->iSign=CVersitRecurrenceMonthlyByPos::CMonthPosition::EWeeksFromStartOfMonth; + TInt numChars; + newMonthPosition->iWeekNo=GetNumberL((*array)[i],numChars); //1-5 + if ((newMonthPosition->iWeekNo<6)&&(newMonthPosition->iWeekNo>0)) + { + newMonthPosition->iArrayOfWeekDays=GetListOfWeekDayOccurrencesL(dayList); + if(newMonthPosition->iArrayOfWeekDays) + { + monthPositions->AppendL(newMonthPosition); + CleanupStack::Pop(newMonthPosition); // + } + else + CleanupStack::PopAndDestroy(newMonthPosition); + } + else + CleanupStack::PopAndDestroy(newMonthPosition); // + + } + CleanupStack::PopAndDestroy(array);// + recurrence=new(ELeave)CVersitRecurrenceMonthlyByPos(aInterval,0,0,monthPositions); + CleanupStack::Pop(monthPositions); // + break; + } + case CVersitRecurrence::EMonthlyByDay: + { + CArrayFix* arrayOfOccurrencesInDaysFromStartOfMonth=new(ELeave)CArrayFixFlat(3); + CleanupStack::PushL(arrayOfOccurrencesInDaysFromStartOfMonth); + CArrayFix* arrayOfOccurrencesInDaysFromEndOfMonth=new(ELeave)CArrayFixFlat(3); + CleanupStack::PushL(arrayOfOccurrencesInDaysFromEndOfMonth); + TBool lastDay=EFalse; + + TPtrC restdates(aListDates); + TPtrC date(aListDates); + TInt posSpace=0; + TInt i=0; + TInt length=aListDates.Length(); + + while(i0) + { + date.Set(restdates.Left(posSpace)); + if(posSpaceAppendL(GetNumberL(date,numChar)); + else + arrayOfOccurrencesInDaysFromStartOfMonth->AppendL(GetNumberL(date,numChar)); + } + else if (date.CompareC(KVersitRecurrenceLastDay))//LD + lastDay=ETrue; + } + + if (arrayOfOccurrencesInDaysFromStartOfMonth->Count()) + { + if (arrayOfOccurrencesInDaysFromEndOfMonth->Count()) + { + recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, arrayOfOccurrencesInDaysFromStartOfMonth, arrayOfOccurrencesInDaysFromEndOfMonth, lastDay); + CleanupStack::Pop(2,arrayOfOccurrencesInDaysFromStartOfMonth); // + } + else + { + recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, arrayOfOccurrencesInDaysFromStartOfMonth, NULL, lastDay); + CleanupStack::PopAndDestroy(); // + arrayOfOccurrencesInDaysFromEndOfMonth = NULL; + CleanupStack::Pop(arrayOfOccurrencesInDaysFromStartOfMonth); // + } + } + else + { + if (arrayOfOccurrencesInDaysFromEndOfMonth->Count()) + { + recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, NULL, arrayOfOccurrencesInDaysFromEndOfMonth, lastDay); + CleanupStack::Pop(arrayOfOccurrencesInDaysFromEndOfMonth); // + } + else + { + recurrence = new(ELeave)CVersitRecurrenceMonthlyByDay(aInterval, 0, 0, NULL, NULL, lastDay); + CleanupStack::PopAndDestroy(arrayOfOccurrencesInDaysFromEndOfMonth); // + arrayOfOccurrencesInDaysFromEndOfMonth = NULL; + } + CleanupStack::PopAndDestroy(arrayOfOccurrencesInDaysFromStartOfMonth); // + arrayOfOccurrencesInDaysFromStartOfMonth = NULL; + } + break; + } + case CVersitRecurrence::EYearlyByMonth: + { + CArrayFix* arrayOfMonthInYearOccurrences=new(ELeave)CArrayFixFlat(3); + CleanupStack::PushL(arrayOfMonthInYearOccurrences); + TInt month; + TInt length=aListDates.Length(); + TPtrC restdates(aListDates); + TPtrC date(aListDates); + TInt posSpace=0; + TInt i=0; + while(i0) + { + date.Set(restdates.Left(posSpace)); + if(posSpace 0) && (month < 13)) + arrayOfMonthInYearOccurrences->AppendL(TMonth(month - 1)); + } + } + + if (arrayOfMonthInYearOccurrences->Count()) + { + recurrence = new(ELeave)CVersitRecurrenceYearlyByMonth(aInterval, 0, 0, arrayOfMonthInYearOccurrences); + CleanupStack::Pop(arrayOfMonthInYearOccurrences); // + } + else + { + recurrence = new(ELeave)CVersitRecurrenceYearlyByMonth(aInterval, 0, 0, NULL); + CleanupStack::PopAndDestroy(arrayOfMonthInYearOccurrences); // + arrayOfMonthInYearOccurrences = NULL; + } + break; + } + case CVersitRecurrence::EYearlyByDay: + { + CArrayFix* arrayOfDayInYearOccurrences=new(ELeave)CArrayFixFlat(3); + CleanupStack::PushL(arrayOfDayInYearOccurrences); + TInt day; + TInt length=aListDates.Length(); + TPtrC restdates(aListDates); + TPtrC date(aListDates); + TInt posSpace=0; + TInt i=0; + while(i0) + { + date.Set(restdates.Left(posSpace)); + if(posSpace 0) && (day < 366)) + arrayOfDayInYearOccurrences->AppendL(day); + } + } + if (arrayOfDayInYearOccurrences->Count()) + { + recurrence = new(ELeave)CVersitRecurrenceYearlyByDay(aInterval, 0, 0, arrayOfDayInYearOccurrences); + CleanupStack::Pop(arrayOfDayInYearOccurrences); //arrayOfDayInYearOccurrences + } + else + { + recurrence = new(ELeave)CVersitRecurrenceYearlyByDay(aInterval, 0, 0, NULL); + CleanupStack::PopAndDestroy(arrayOfDayInYearOccurrences); //arrayOfDayInYearOccurrences + arrayOfDayInYearOccurrences = NULL; + } + break; + } + }; + return recurrence; + } + +CWeekDayArray* CRecurrenceParser::GetListOfWeekDayOccurrencesL(const TDesC& aListDays) + { + if (aListDays.Length()==0) + return NULL; + CWeekDayArray* arrayOfWeekDayOccurrences = new(ELeave)CWeekDayArray; + CleanupStack::PushL(arrayOfWeekDayOccurrences); + arrayOfWeekDayOccurrences->iArray = new(ELeave)CArrayFixFlat(3); + TPtrC restdays(aListDays); + TPtrC day(aListDays); + TInt posSpace=0; + while(posSpace!=KErrNotFound) + { + posSpace=restdays.Locate(ESpace); + if(posSpace>0) + { + day.Set(restdays.Left(posSpace)); + if(posSpaceiArray->AppendL(EFriday); + break; + case 'M': + if (!day.CompareC(KVersitRecurrenceMonday)) + arrayOfWeekDayOccurrences->iArray->AppendL(EMonday); + break; + case 'S': + if (!day.CompareC(KVersitRecurrenceSaturday())) + arrayOfWeekDayOccurrences->iArray->AppendL(ESaturday); + else if (!day.CompareF(KVersitRecurrenceSunday)) + arrayOfWeekDayOccurrences->iArray->AppendL(ESunday); + break; + case 'T': + if (!day.CompareC(KVersitRecurrenceTuesday)) + arrayOfWeekDayOccurrences->iArray->AppendL(ETuesday); + else if (!day.CompareF(KVersitRecurrenceThursday)) + arrayOfWeekDayOccurrences->iArray->AppendL(EThursday); + break; + case 'W': + if (!day.CompareC(KVersitRecurrenceWednesday)) + arrayOfWeekDayOccurrences->iArray->AppendL(EWednesday); + break; + default: + User::Leave(KVersitErrBadRepeatValue); + } + } + CleanupStack::Pop(arrayOfWeekDayOccurrences); + if (arrayOfWeekDayOccurrences->iArray->Count()) + return arrayOfWeekDayOccurrences; + delete arrayOfWeekDayOccurrences; + return NULL; + } + +EXPORT_C void CRecurrenceParser::Reserved1() + {} + +EXPORT_C void CRecurrenceParser::Reserved2() + {}