--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/meetingrequest/mrversit2/src/cesmricalvalue.cpp Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1505 @@
+/*
+* Copyright (c) 2002-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: This file implements class CESMRICalValue.
+*
+*/
+
+
+// Class include.
+#include "emailtrace.h"
+#include "cesmricalvalue.h" // CESMRICalValue
+
+//debug
+
+// User includes.
+#include "esmricalkeywords.h" // Literals
+#include "cesmricalrulesegment.h" // CESMRICalRuleSegment
+
+// Constants.
+
+namespace{
+// Maximum number of characters to use for storing TInt.
+// (The maximum number of characters for storing a decimal representation of
+// KMaxTInt, KMinTInt or even KMaxTUint is 10 on current implementations.
+// The maximum number of characters for storing a decimal representation of
+// KMaxTUint64 is 20, so using this for future proofing.)
+const TInt KICalTIntWidth = 20;
+
+// Width of "HHMMSS"
+const TInt KICalTimeWidth = 6;
+
+// Width of "YYYYMMDD"
+const TInt KICalDateWidth = 8;
+
+// Width of "YYYYMMDDTHHMMSS" (note the 'T' in the middle)
+const TInt KICalDateTimeWidth = KICalDateWidth + KICalTimeWidth + 1;
+
+// Width of a duration.
+const TInt KICalDurationWidth = 25;
+
+// Width of a short format UTC offset.
+const TInt KShortFormatUtcOffsetWidth = 5; // The width of (e.g.) +1000.
+
+// Width of a long format UTC offset.
+const TInt KLongFormatUtcOffsetWidth = 7; // The width of (e.g.) -013045.
+
+// Time constants.
+const TInt KICalSecondsPerMinute = 60;
+const TInt KICalSecondsPerHour = 3600; // That is: 60*60;
+const TInt KICalSecondsPerDay = 86400; // That is: 24*60*60;
+const TInt KICalSecondsPerWeek = 604800; // That is: 7*24*60*60;
+
+// Time characters
+const TUint KICalUtcChar('Z'); // UTC time.
+const TUint KICalTimeChar('T'); // Date/time separator.
+const TUint KICalPeriodChar('/'); // Period separator.
+const TUint KICalMicroChar('.'); // Second/microsecond separator.
+const TUint KICalDurationChar('P'); // Duration.
+const TUint KICalWeekChar('W'); // Week.
+const TUint KICalDayChar('D'); // Day.
+const TUint KICalHourChar('H'); // Hour.
+const TUint KICalMinuteChar('M'); // Minute.
+const TUint KICalSecondChar('S'); // Second.
+const TUint KICalPositiveChar('+'); // Positive values.
+const TUint KICalNegativeChar('-'); // Negative values.
+
+// Date format.
+_LIT(KICalDateFormat, "%F%Y%M%D");
+}//namespace
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRICalValue* CESMRICalValue::NewL()
+ {
+ FUNC_LOG;
+
+ CESMRICalValue* self = CESMRICalValue::NewLC();
+ CleanupStack::Pop(self);
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::NewLC
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CESMRICalValue* CESMRICalValue::NewLC()
+ {
+ FUNC_LOG;
+
+ CESMRICalValue* self = new (ELeave) CESMRICalValue;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::~CESMRICalValue
+// ---------------------------------------------------------------------------
+//
+CESMRICalValue::~CESMRICalValue()
+ {
+ FUNC_LOG;
+ delete iValue;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::BinaryLC
+// ---------------------------------------------------------------------------
+//
+EXPORT_C HBufC8* CESMRICalValue::BinaryLC() const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+ HBufC8* buf = HBufC8::NewLC(iValue->Length());
+ buf->Des().Copy(*iValue);
+
+ return buf;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetBinaryL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetBinaryL(const TDesC8& aBuffer)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+ iValue = HBufC::NewL(aBuffer.Length());
+ iValue->Des().Copy(aBuffer);
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::BooleanL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TBool CESMRICalValue::BooleanL() const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+
+ if (iValue->Des() == KICalTrue)
+ {
+ return ETrue;
+ }
+ else if (iValue->Des() == KICalFalse)
+ {
+ return EFalse;
+ }
+
+ // Else...
+ User::Leave(KErrCorrupt);
+
+ return EFalse; // Never reached.
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetBooleanL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetBooleanL(TBool aBool)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+
+ if (aBool) // ETrue
+ {
+ iValue = KICalTrue().AllocL();
+ }
+ else // EFalse
+ {
+ iValue = KICalFalse().AllocL();
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDateL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::GetDateL(TTime& aDate) const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+ GetDateFromValueL(aDate);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetDateL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetDateL(const TTime& aDate)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+ iValue = HBufC::NewL(KICalDateWidth);
+ AppendDateToValueL(aDate);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetTimeL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::GetTimeL(TTime& aTime, TTimeZoneType& aTzType) const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+ GetTimeFromValueL(aTime, aTzType);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetTimeL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetTimeL(const TTime& aTime, TTimeZoneType aTzType)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+
+ if (aTzType == EUtcTime)
+ {
+ iValue = HBufC::NewL(KICalTimeWidth + 1);
+ AppendTimeToValueL(aTime);
+ iValue->Des().Append(KICalUtcChar); // Append a 'Z' to signify UTC.
+ }
+ else if (aTzType == ESpecifiedTimeZone || aTzType == EFloatingTime)
+ {
+ iValue = HBufC::NewL(KICalTimeWidth);
+ AppendTimeToValueL(aTime);
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDateTimeL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::GetDateTimeL(TTime& aDateTime, TTimeZoneType& aTzType, TInt aFirstCharacterNum) const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+
+ // The GetTimeFromValueL() function explicitly sets the TTime passed
+ // in, so create a new TTime for the date and merge with the time later.
+ TTime theDate;
+ GetDateFromValueL(theDate, aFirstCharacterNum);
+
+ // Only start looking for the time at character position KICalDateWidth
+ // plus one for the 'T' separator.
+ if (iValue->Length() > aFirstCharacterNum + KICalDateWidth + 1)
+ {
+ TTime theTime;
+ if ((*iValue)[aFirstCharacterNum + KICalDateWidth] != KICalDateTimeSeparator)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ GetTimeFromValueL(theTime, aTzType, aFirstCharacterNum + KICalDateWidth + 1);
+
+ // Set the time component.
+ TDateTime dateValues(theDate.DateTime());
+ TDateTime combinedValues(theTime.DateTime());
+
+ // Set the date component.
+ combinedValues.SetYear(dateValues.Year());
+ combinedValues.SetMonth(dateValues.Month());
+ combinedValues.SetDay(dateValues.Day());
+
+ // Set the value to return.
+ aDateTime = TTime(combinedValues);
+ }
+ else
+ {
+ // There is no time component specified. For compatibility with MS Outlook,
+ // which can export RECURRENCE-ID fields with no time component, we use
+ // a default time of '00:00'
+ aDateTime = theDate;
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetDateTimeL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetDateTimeL(const TTime& aDateTime, TTimeZoneType aTzType)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+
+ if (aTzType == EUtcTime)
+ {
+ iValue = HBufC::NewL(KICalDateTimeWidth + 1);
+ AppendDateToValueL(aDateTime);
+
+ iValue->Des().Append(KICalTimeChar);
+ AppendTimeToValueL(aDateTime);
+
+ iValue->Des().Append(KICalUtcChar); // For UTC Time.
+ }
+ else if (aTzType == ESpecifiedTimeZone || aTzType == EFloatingTime)
+ {
+ iValue = HBufC::NewL(KICalDateTimeWidth);
+ AppendDateToValueL(aDateTime);
+
+ iValue->Des().Append(KICalTimeChar);
+ AppendTimeToValueL(aDateTime);
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::DurationL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TTimeIntervalSeconds CESMRICalValue::DurationL() const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+ TTimeIntervalSeconds theTis;
+ GetTimeIntervalFromValueL(theTis);
+
+ return theTis;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetDurationL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetDurationL(TTimeIntervalSeconds aDuration)
+ {
+ FUNC_LOG;
+
+ // e.g. P15DT5H0M20S
+ PrepareValuePointer();
+
+ iValue = HBufC::NewL(KICalDurationWidth);
+ TInt durInt(aDuration.Int());
+
+ if (durInt < 0)
+ {
+ // First character is a '-' for negative values
+ iValue->Des().Append(KICalNegativeChar);
+
+ // Now we've set the sign, change the durInt to +ve
+ durInt =- durInt;
+ }
+
+ iValue->Des().Append(KICalDurationChar);
+
+ // Add day portion.
+ TInt numDays(durInt / KICalSecondsPerDay);
+ durInt -= (numDays * KICalSecondsPerDay);
+ iValue->Des().AppendNum(numDays);
+ iValue->Des().Append(KICalDayChar);
+ iValue->Des().Append(KICalTimeChar);
+
+ // Add hour portion.
+ TInt numHours(durInt / KICalSecondsPerHour);
+ durInt -= (numHours * KICalSecondsPerHour);
+ iValue->Des().AppendNum(numHours);
+ iValue->Des().Append(KICalHourChar);
+
+ // Add minute portion.
+ TInt numMinutes(durInt / KICalSecondsPerMinute);
+ durInt -= (numMinutes * KICalSecondsPerMinute);
+ iValue->Des().AppendNum(numMinutes);
+ iValue->Des().Append(KICalMinuteChar);
+
+ // Add second portion.
+ TInt numSeconds(durInt);
+ iValue->Des().AppendNum(numSeconds);
+ iValue->Des().Append(KICalSecondChar);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetFloatL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::GetFloatL(TReal& aFloat) const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+ TLex stringLex(iValue->Des());
+ User::LeaveIfError(stringLex.Val(aFloat));
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetFloatL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetFloatL(const TReal& aFloat)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+
+ iValue = HBufC::NewL(KDefaultRealWidth);
+ TRealFormat format;
+ iValue->Des().Num(aFloat, format);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::IntegerL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CESMRICalValue::IntegerL() const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+
+ return ReadIntL(iValue->Des());
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetIntegerL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetIntegerL(TInt aInt)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+ iValue = HBufC::NewL(KICalTIntWidth);
+ iValue->Des().Num(aInt);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetPeriodL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::GetPeriodL(
+ TTime& aStartTime,
+ TTimeZoneType& aStartTzType,
+ TTime& aEndTime,
+ TTimeZoneType& aEndTzType) const
+ {
+ FUNC_LOG;
+
+ // Example : 19970101T180000Z/19970102T070000Z
+ // that is : yyyymmddThhmmss[Z]/yyyymmddThhmmss[Z]
+
+ // Example2: 19970101T180000Z/PT5H30M
+ // that is2: yyyymmddThhmmss[Z]/[+/-]P[lots of stuff]
+
+ // As the first part is always a date-time, get this out to start off with
+ GetDateTimeL(aStartTime, aStartTzType, 0);
+
+ // Next we need to get the position of the separator.
+ TInt charNumber(iValue->Des().Locate(KICalPeriodChar));
+ User::LeaveIfError(charNumber);
+
+ // If the character after the separator is a 'P', '+' or '-' the second part is a duration.
+ ++charNumber;
+ if (charNumber >= iValue->Length())
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ TChar theChar(iValue->Des()[charNumber]);
+
+ if ((theChar == KICalDurationChar) ||
+ (theChar == KICalPositiveChar) ||
+ (theChar == KICalNegativeChar))
+ {
+ // Call a function to change the duration into a TTime (date + time)
+ TTimeIntervalSeconds interval;
+ GetTimeIntervalFromValueL(interval, charNumber);
+
+ // Convert from this TimeInterval to a TTime
+ aEndTime = aStartTime;
+ aEndTime += interval;
+
+ // The timezone will be the same as the first.
+ aEndTzType = aStartTzType;
+ }
+ else // Presume it's a date-time
+ {
+ GetDateTimeL(aEndTime, aEndTzType, charNumber);
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetPeriodL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetPeriodL(
+ const TTime& aStartTime,
+ TTimeZoneType aStartTzType,
+ const TTime& aEndTime,
+ TTimeZoneType aEndTzType)
+ {
+ FUNC_LOG;
+
+ // Example: 19970101T180000Z/19970102T070000Z
+ // that is: yyyymmddThhmmss[Z]/yyyymmddThhmmss[Z]
+
+ PrepareValuePointer();
+
+ SetDateTimeL(aStartTime, aStartTzType);
+
+ if (aEndTzType == EUtcTime)
+ {
+ iValue->ReAllocL(iValue->Length() + 2 + KICalDateTimeWidth);
+ iValue->Des().Append(KICalPeriodChar);
+
+ AppendDateToValueL(aEndTime);
+ iValue->Des().Append(KICalTimeChar);
+
+ AppendTimeToValueL(aEndTime);
+ iValue->Des().Append(KICalUtcChar);
+ }
+ else if (aEndTzType == ESpecifiedTimeZone || aEndTzType == EFloatingTime)
+ {
+ iValue->ReAllocL(iValue->Length() + 1 + KICalDateTimeWidth);
+
+ iValue->Des().Append(KICalPeriodChar);
+ AppendDateToValueL(aEndTime);
+
+ iValue->Des().Append(KICalTimeChar);
+ AppendTimeToValueL(aEndTime);
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDayL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::GetDayL(TDay& aDay, TInt& aPos) const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+
+ // Find the end of the numeric part.
+ _LIT(KICalDayNumeric, "-+0123456789");
+ TInt endNumeric(0);
+
+ while (endNumeric < iValue->Length())
+ {
+ if (KICalDayNumeric().Locate((*iValue)[endNumeric]) == KErrNotFound)
+ {
+ break;
+ }
+
+ ++endNumeric;
+ }
+
+ // Set the numeric part.
+ if (endNumeric != 0)
+ {
+ aPos = ReadIntL(iValue->Left(endNumeric));
+ }
+ else
+ {
+ aPos = 0;
+ }
+
+ // Set the day part.
+ HBufC* dayStrBuf = iValue->Mid(endNumeric).AllocLC();
+ TPtr dayStr( dayStrBuf->Des() );
+ dayStr.TrimLeft();
+
+ if (dayStr.CompareF(KICalMonday) == 0)
+ {
+ aDay = EMonday;
+ }
+ else if (dayStr.CompareF(KICalTuesday) == 0)
+ {
+ aDay = ETuesday;
+ }
+ else if (dayStr.CompareF(KICalWednesday) == 0)
+ {
+ aDay = EWednesday;
+ }
+ else if (dayStr.CompareF(KICalThursday) == 0)
+ {
+ aDay = EThursday;
+ }
+ else if (dayStr.CompareF(KICalFriday) == 0)
+ {
+ aDay = EFriday;
+ }
+ else if (dayStr.CompareF(KICalSaturday) == 0)
+ {
+ aDay = ESaturday;
+ }
+ else if (dayStr.CompareF(KICalSunday) == 0)
+ {
+ aDay = ESunday;
+ }
+ else
+ {
+ User::Leave(KErrCorrupt); // Invalid day.
+ }
+
+ CleanupStack::PopAndDestroy( dayStrBuf );
+ dayStrBuf = NULL;
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetDayL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetDayL(TDay aDay, TInt aPos)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+
+ // Get the day as a descriptor.
+ TPtrC dayName;
+
+ switch (aDay)
+ {
+ case EMonday:
+ dayName.Set(KICalMonday());
+ break;
+ case ETuesday:
+ dayName.Set(KICalTuesday());
+ break;
+ case EWednesday:
+ dayName.Set(KICalWednesday());
+ break;
+ case EThursday:
+ dayName.Set(KICalThursday());
+ break;
+ case EFriday:
+ dayName.Set(KICalFriday());
+ break;
+ case ESaturday:
+ dayName.Set(KICalSaturday());
+ break;
+ case ESunday:
+ dayName.Set(KICalSunday());
+ break;
+ default:
+ User::Leave(KErrUnknown);
+ break;
+ }
+
+ // We need space for a number and a day name.
+ iValue = HBufC::NewL(KICalTIntWidth + dayName.Length());
+ iValue->Des().AppendNum(aPos);
+ iValue->Des().Append(dayName);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::MonthL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TMonth CESMRICalValue::MonthL() const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+
+ TInt num(IntegerL());
+
+ if ((num < 1) || (num > 12))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ return static_cast<TMonth>(num - 1);
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetMonthL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetMonthL(TMonth aMonth)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+ SetIntegerL(aMonth + 1);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetRecurrenceRuleL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::GetRecurrenceRuleL(RPointerArray<CESMRICalRuleSegment>& aRuleSegmentArray) const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+
+ // Find the first semicolon:
+ TInt nextSemiColon(iValue->Locate(KICalSemiColonChar));
+
+ if (nextSemiColon == KErrNotFound)
+ {
+ // This means there is only one segment, pretend the semicolon exists at the end of the buffer
+ nextSemiColon = iValue->Length();
+ }
+
+ TUint charNum(0);
+
+ do
+ {
+ // Create a rule segment from characters charNum to nextSemiColon
+ CESMRICalRuleSegment* theRule = CESMRICalRuleSegment::NewLC(iValue->Mid(charNum, nextSemiColon - charNum));
+ User::LeaveIfError(aRuleSegmentArray.Append(theRule)); // Takes ownership.
+ CleanupStack::Pop(theRule);
+
+ // Put the character marker past the current semicolon
+ charNum = nextSemiColon + 1;
+
+ // We only want to check for any more semicolons in the area to the right of charNum.
+ // First check if there are ANY characters to the right of charNum
+ if (charNum < iValue->Length())
+ {
+ // Find the location of the next semi colon in this area.
+ nextSemiColon = iValue->Right(iValue->Length() - charNum).Locate(KICalSemiColonChar);
+
+ if (nextSemiColon != KErrNotFound)
+ {
+ // Set the semicolon to be in it's correct position, shifted to take into account the fact
+ // that we were only looking in the right part of the original descriptor.
+ nextSemiColon += charNum;
+ }
+ else
+ {
+ // There are no more semicolons, read in the last value and then exit the loop
+ nextSemiColon = iValue->Length();
+ }
+ }
+ }
+ while (charNum < iValue->Length());
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetRecurrenceRuleL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetRecurrenceRuleL(const TDesC& aRuleValue)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+ iValue = aRuleValue.AllocL();
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::TextL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C const TDesC& CESMRICalValue::TextL() const
+ {
+ FUNC_LOG;
+
+ CheckNullValueL();
+
+ return *iValue;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetTextL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetTextL(const TDesC& aText)
+ {
+ FUNC_LOG;
+
+ PrepareValuePointer();
+ iValue = aText.AllocL();
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::UtcOffsetL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TTimeIntervalSeconds CESMRICalValue::UtcOffsetL() const
+ {
+ FUNC_LOG;
+
+ // Format is (e.g.) +1000 (10 hours ahead) or -013045 (1.5 hours and 45 seconds behind).
+ CheckNullValueL();
+
+ const TInt length = iValue->Length();
+
+ if ((length != KLongFormatUtcOffsetWidth) && (length != KShortFormatUtcOffsetWidth))
+ {
+ // Invalid UTC Offset - we can't really test more than this, so the output may be garbage
+ User::Leave(KErrCorrupt);
+ }
+
+ // Get the value of the hour component.
+ TInt hours(ReadIntL(iValue->Des().Left(3))); // '+' or '-' plus the hours component.
+
+ // Get the value of the minute component.
+ TInt minutes(ReadIntL(iValue->Des().Mid(3, 2))); // The minutes component.
+
+ // Get the value of the (optional) second component.
+ TInt seconds(0);
+
+ if (length == KLongFormatUtcOffsetWidth) // Long format.
+ {
+ seconds = ReadIntL(iValue->Des().Mid(5, 2)); // The second component.
+ }
+
+ // Convert to TTimeIntervalSeconds.
+ return TTimeIntervalSeconds((hours * KICalSecondsPerHour) + (minutes * KICalSecondsPerMinute) + seconds);
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::SetUtcOffsetL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CESMRICalValue::SetUtcOffsetL(TTimeIntervalSeconds aOffset)
+ {
+ FUNC_LOG;
+
+ // Format is (e.g.) +1000 (10 hours ahead) or -013045 (1.5 hours and 45 seconds behind).
+ PrepareValuePointer();
+
+ // Create a buffer long enough to hold the widest format.
+ iValue = HBufC::NewL(KLongFormatUtcOffsetWidth);
+
+ // Get the offset as an integer.
+ TInt offset(aOffset.Int());
+
+ // Set the sign.
+ if (offset < 0)
+ {
+ iValue->Des().Append(KICalNegativeChar);
+
+ // Set offset to positive for calculations.
+ offset =- offset;
+ }
+ else
+ {
+ iValue->Des().Append(KICalPositiveChar);
+ }
+
+ // Add hour portion.
+ TInt numHours(offset / KICalSecondsPerHour);
+ offset -= (numHours * KICalSecondsPerHour);
+ iValue->Des().AppendNumFixedWidth(numHours, EDecimal, 2);
+
+ // Add minute portion.
+ TInt numMinutes(offset / KICalSecondsPerMinute);
+ offset -= (numMinutes * KICalSecondsPerMinute);
+ iValue->Des().AppendNumFixedWidth(numMinutes, EDecimal, 2);
+
+ // Add second portion if necessary.
+ if (offset > 0)
+ {
+ iValue->Des().AppendNumFixedWidth(offset, EDecimal, 2);
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::CESMRICalValue
+// ---------------------------------------------------------------------------
+//
+CESMRICalValue::CESMRICalValue()
+ {
+ FUNC_LOG;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CESMRICalValue::ConstructL()
+ {
+ FUNC_LOG;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::CheckNullValueL
+// ---------------------------------------------------------------------------
+//
+/**
+Checks for a NULL value. Should be called before accessing iValue.
+@leave Leaves with KErrCorrupt if the value is NULL.
+@internalTechnology
+*/
+void CESMRICalValue::CheckNullValueL() const
+ {
+ FUNC_LOG;
+
+ if (!iValue)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::PrepareValuePointer
+// ---------------------------------------------------------------------------
+//
+/**
+Prepares iValue pointer for writing. Deletes existing pointer if it exists.
+@internalTechnology
+*/
+void CESMRICalValue::PrepareValuePointer()
+ {
+ FUNC_LOG;
+
+ if (iValue)
+ {
+ delete iValue;
+ iValue = NULL;
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::ReadIntL
+// ---------------------------------------------------------------------------
+//
+/**
+Reads a TInt from the given descriptor.
+@param aDes The descriptor to convert
+@return The integer conversion.
+@leave Leaves if there is an error reading an integer.
+@internalTechnology
+*/
+TInt CESMRICalValue::ReadIntL(const TDesC& aDes) const
+ {
+ FUNC_LOG;
+
+ TLex stringLex(aDes);
+ TInt returnValue(0);
+ User::LeaveIfError(stringLex.Val(returnValue));
+
+ return returnValue;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::AppendDateToValueL
+// ---------------------------------------------------------------------------
+//
+/**
+Appends the date to iValue. Member iValue must be initialised before calling.
+@param aDate TTime to append to the value.
+@internalTechnology
+*/
+void CESMRICalValue::AppendDateToValueL(const TTime& aDate)
+ {
+ FUNC_LOG;
+
+ TBuf<KICalDateWidth> formattedDate;
+ aDate.FormatL(formattedDate, KICalDateFormat);
+ iValue->Des().Append(formattedDate);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDateFromValueL
+// ---------------------------------------------------------------------------
+//
+/**
+Gets the date from iValue descriptor. Should be in the format YYYYMMDD
+@param aDate A modifiable reference returning a date.
+@param aFirstCharacterNum Skip this many characters at the start of the value.
+@leave Leaves with KErrCorrupt if the format of the value is not a valid date.
+@internalTechnology
+*/
+void CESMRICalValue::GetDateFromValueL(TTime& aDate, TInt aFirstCharacterNum) const
+ {
+ FUNC_LOG;
+
+ if (aFirstCharacterNum + KICalDateWidth > iValue->Length())
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Get the year as an int.
+ TInt year(ReadIntL(iValue->Des().Mid(aFirstCharacterNum, 4))); // YYYYmmdd
+
+ if (year < 0) // All positive years are valid
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Get the month as an int.
+ TInt month(ReadIntL(iValue->Mid(aFirstCharacterNum + 4, 2))); // yyyMMdd
+
+ if ((month < 1) || (month > 12))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Get the day as an int.
+ TInt day(ReadIntL(iValue->Mid(aFirstCharacterNum + 6, 2))); // yyyymmDD
+
+ if ((day < 1) || (day > Time::DaysInMonth(year, static_cast<TMonth>(month - 1)))) // Zero-offset month.
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Set the date from its component parts.
+ aDate = 0;
+ aDate += TTimeIntervalYears(year);
+ aDate += TTimeIntervalMonths(month - 1); // Zero-offset.
+ aDate += TTimeIntervalDays(day - 1); // Zero-offset.
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::AppendTimeToValueL
+// ---------------------------------------------------------------------------
+//
+/**
+Appends the time to iValue. Member iValue must be initialised before calling.
+@param aTime TTime to append to the value.
+@internalTechnology
+*/
+void CESMRICalValue::AppendTimeToValueL(const TTime& aTime)
+ {
+ FUNC_LOG;
+
+ // Format is HHMMSS followed optionally by a Z for UTC time.
+ // Note that the 'Z' is not appended here.
+ TDateTime fullTime(aTime.DateTime());
+
+ iValue->Des().AppendNumFixedWidth(fullTime.Hour(), EDecimal, 2);
+ iValue->Des().AppendNumFixedWidth(fullTime.Minute(), EDecimal, 2);
+ iValue->Des().AppendNumFixedWidth(fullTime.Second(), EDecimal, 2);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetTimeFromValueL
+// ---------------------------------------------------------------------------
+//
+/**
+Gets the time from iValue descriptor, starting from a pre-determined point.
+Should be in the format HHMMSS[Z]
+@param aTime TTime to store result of read in
+@param aTzType Enumeration showing whether the time represents local time (not
+supported), UTC or a custom time zone.
+@param aFirstCharacterNum The character number to start searching from.
+@leave Leaves with KErrCorrupt if the value does not hold a valid time.
+@internalTechnology
+*/
+void CESMRICalValue::GetTimeFromValueL(TTime& aTime, TTimeZoneType& aTzType, TInt aFirstCharacterNum) const
+ {
+ FUNC_LOG;
+
+ if (aFirstCharacterNum + KICalTimeWidth > iValue->Length())
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Create a new descriptor containing just the first KICalTimeWidth characters of iValue
+ // It's size is one larger as we will need to add a full stop (see below)
+ HBufC* formattedTime = HBufC::NewLC(iValue->Des().Mid(aFirstCharacterNum, KICalTimeWidth).Length() + 1);
+ *formattedTime = iValue->Des().Mid(aFirstCharacterNum, KICalTimeWidth);
+
+ // The only formatting needed is to append a full stop
+ formattedTime->Des().Append(KICalMicroChar);
+
+ if (aTime.Set(*formattedTime))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ if ((iValue->Length() > (KICalTimeWidth + aFirstCharacterNum)) &&
+ (iValue->Des()[KICalTimeWidth + aFirstCharacterNum] == KICalUtcChar))
+ {
+ aTzType = EUtcTime;
+ }
+ else
+ {//DAVIDTODO:
+ // If there is no 'Z' character then assume that there
+ // is a specified time zone - EFloatingTime is not used.
+ aTzType = ESpecifiedTimeZone;
+ }
+
+ CleanupStack::PopAndDestroy(formattedTime);
+
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetTimeIntervalFromValueL
+// ---------------------------------------------------------------------------
+//
+/**
+Retrieves a time interval stored as a duration as per the RFC 2445
+specification.
+@param aTimeInterval TTimeIntervalSeconds to store the result in.
+@param aFirstCharacterNum The position in the value containing the first
+character of the duration.
+@leave Leaves with KErrCorrupt if the value does not hold a valid interval.
+@internalTechnology
+*/
+void CESMRICalValue::GetTimeIntervalFromValueL(TTimeIntervalSeconds& aTimeInterval, TInt aFirstCharacterNum) const
+ {
+ FUNC_LOG;
+
+ // dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
+ // dur-date = dur-day [dur-time]
+ // dur-time = "T" (dur-hour / dur-minute / dur-second)
+ // dur-week = 1*DIGIT "W"
+ // dur-hour = 1*DIGIT "H" [dur-minute]
+ // dur-minute = 1*DIGIT "M" [dur-second]
+ // dur-second = 1*DIGIT "S"
+ // dur-day = 1*DIGIT "D"
+
+ // Example: A duration of 15 days, 5 hours and 20 seconds would be:
+ // P15DT5H0M20S
+ // A duration of 7 weeks would be:
+ // P7W
+
+ TInt intervalMultiplier(1); // This variable sets the interval to be positive or negative.
+
+ // Length should be at least two.
+ if ((aFirstCharacterNum >= iValue->Length()) || (iValue->Length() < 2 + aFirstCharacterNum))
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // Check that the first character is a 'P', '+' or '-' and adjust the interval accordingly.
+ TChar firstCharacter(iValue->Des()[aFirstCharacterNum]);
+
+ if (firstCharacter == KICalDurationChar)
+ {
+ intervalMultiplier = 1;
+ aFirstCharacterNum += 1; // Skip the "P"
+ }
+ else if (firstCharacter == KICalPositiveChar)
+ {
+ intervalMultiplier = 1;
+ aFirstCharacterNum += 2; // Skip the "+P"
+ }
+ else if (firstCharacter == KICalNegativeChar)
+ {
+ intervalMultiplier = -1;
+ aFirstCharacterNum += 2; // Skip the "-P"
+ }
+ else
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ // It can only contain a dur-date, or a dur-time, or a dur-week
+ TInt theInterval(0);
+ if (!GetDurDateL(theInterval, aFirstCharacterNum))
+ {
+ if (!GetDurTimeL(theInterval, aFirstCharacterNum))
+ {
+ if (!GetDurWeekL(theInterval, aFirstCharacterNum))
+ {
+ User::Leave(KErrCorrupt);
+ }
+ }
+ }
+
+ theInterval *= intervalMultiplier;
+
+ // Now we've done the multiply we can convert it into a TTimeIntervalSeconds
+ aTimeInterval = theInterval;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDurDateL
+// ---------------------------------------------------------------------------
+//
+/**
+Reads in and converts a dur-day into a number of seconds
+@param aIntervalSecs Function adds number of seconds to this variable.
+@param aCurrentCharNumber Character number to start looking in the value.
+@return ETrue if the value could be interpreted as a dur-date, EFalse otherwise.
+@internalTechnology
+*/
+TBool CESMRICalValue::GetDurDateL(TInt& aIntervalSecs, TInt& aCurrentCharNumber) const
+ {
+ FUNC_LOG;
+
+ // dur-date = dur-day [dur-time]
+ // dur-day = 1*DIGIT "D"
+
+ if (aCurrentCharNumber >= iValue->Length())
+ {
+ return EFalse;
+ }
+
+ // Create a new TPtrC containing the data from iValue which we need.
+ TPtrC data(iValue->Mid(aCurrentCharNumber));
+
+ // Find the next 'D' in the descriptor.
+ TInt nextDPos(data.Locate(KICalDayChar));
+
+ // Check it exists
+ if (nextDPos != KErrNotFound)
+ {
+ // If character found, construct a number from currentCharNumber to nextDPos
+ TInt theNum(ReadIntL(data.Left(nextDPos)));
+
+ // Convert this time from days to seconds
+ theNum *= KICalSecondsPerDay;
+ aIntervalSecs += theNum;
+ aCurrentCharNumber += nextDPos + 1; // Extra increment to get past the 'D'
+
+ // Check if a dur-time follows. It's optional
+ // so we can ignore it's return value.
+ GetDurTimeL(aIntervalSecs, aCurrentCharNumber);
+ return ETrue;
+ }
+
+ // If no character found, return EFalse
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDurTimeL
+// ---------------------------------------------------------------------------
+//
+/**
+Reads in and converts a dur-time into a number of seconds
+@param aIntervalSecs Function adds number of seconds to this variable.
+@param aCurrentCharNumber Character number to start looking in the value.
+@return ETrue if the value could be interpreted as a dur-time, EFalse otherwise.
+@leave Leaves with KErrCorrupt if the value does not hold a valid time.
+@internalTechnology
+*/
+TBool CESMRICalValue::GetDurTimeL(TInt& aIntervalSecs, TInt& aCurrentCharNumber) const
+ {
+ FUNC_LOG;
+
+ // dur-time = "T" (dur-hour / dur-minute / dur-second) e.g. T5H0M20S
+
+ if (aCurrentCharNumber >= iValue->Length())
+ {
+ return EFalse;
+ }
+
+ if (iValue->Des()[aCurrentCharNumber] == KICalTimeChar)
+ {
+ ++aCurrentCharNumber; // Increment to get past 'T'
+
+ if (!GetDurHourL(aIntervalSecs, aCurrentCharNumber))
+ {
+ if (!GetDurMinuteL(aIntervalSecs, aCurrentCharNumber))
+ {
+ if (!GetDurSecondL(aIntervalSecs, aCurrentCharNumber))
+ {
+ // We should not have read a 'T' and failed to match hour/minute/second
+ User::Leave(KErrCorrupt);
+ }
+ }
+ }
+ }
+ else
+ {
+ // First character is not a 'T', therefore value is not a dur-time
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDurHourL
+// ---------------------------------------------------------------------------
+//
+/**
+Reads in and converts a dur-hour into a number of seconds. There is no range
+check on the number of hours.
+@param aIntervalSecs Function adds number of seconds to this variable.
+@param aCurrentCharNumber Character number to start looking in the value.
+@return ETrue if the value could be interpreted as a dur-hour, EFalse otherwise.
+@internalTechnology
+*/
+TBool CESMRICalValue::GetDurHourL(TInt& aIntervalSecs, TInt& aCurrentCharNumber) const
+ {
+ FUNC_LOG;
+
+ // dur-hour = 1*DIGIT "H" [dur-minute]
+
+ if (aCurrentCharNumber >= iValue->Length())
+ {
+ return EFalse;
+ }
+
+ // Create a new TPtrC containing the data from iValue which we need
+ TPtrC data(iValue->Mid(aCurrentCharNumber));
+
+ // Find the next 'H' in the descriptor
+ TInt nextHPos(data.Locate(KICalHourChar));
+
+ // Check it exists
+ if (nextHPos != KErrNotFound)
+ {
+ // If character found, construct a number from currentCharNumber to nextHPos
+ TInt theNum(ReadIntL(data.Left(nextHPos)));
+
+ // Convert this time from hours to seconds
+ theNum *= KICalSecondsPerHour;
+
+ aIntervalSecs += theNum;
+ aCurrentCharNumber += nextHPos + 1; // Extra increment to get past 'H'
+
+ // Check if a dur-minute follows. It's optional
+ // so we can ignore it's return value.
+ GetDurMinuteL(aIntervalSecs,aCurrentCharNumber);
+ return ETrue;
+ }
+
+ // If no character found, return EFalse
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDurMinuteL
+// ---------------------------------------------------------------------------
+//
+/**
+Reads in and converts a dur-minute into a number of seconds. There is no range
+check on the number of minutes.
+@param aIntervalSecs Function adds number of seconds to this variable.
+@param aCurrentCharNumber Character number to start looking in the value.
+@return ETrue if the value could be interpreted as a dur-minute, EFalse
+otherwise.
+@internalTechnology
+*/
+TBool CESMRICalValue::GetDurMinuteL(TInt& aIntervalSecs, TInt& aCurrentCharNumber) const
+ {
+ FUNC_LOG;
+
+ // dur-minute = 1*DIGIT "M" [dur-second]
+
+ if (aCurrentCharNumber >= iValue->Length())
+ {
+ return EFalse;
+ }
+
+ // Create a new TPtrC containing the data from iValue which we need
+ TPtrC data(iValue->Mid(aCurrentCharNumber));
+
+ // Find the next 'M' in the descriptor
+ TInt nextMPos(data.Locate(KICalMinuteChar));
+
+ // Check it exists
+ if (nextMPos != KErrNotFound)
+ {
+ // If character found, construct a number from currentCharNumber to nextMPos
+ TInt theNum(ReadIntL(data.Left(nextMPos)));
+
+ // Convert this time from minutes to seconds
+ theNum *= KICalSecondsPerMinute;
+
+ aIntervalSecs += theNum;
+ aCurrentCharNumber += nextMPos + 1; // Extra increment to get past 'M'
+
+ // Check if a dur-second follows. It's optional
+ // so we can ignore it's return value.
+ GetDurSecondL(aIntervalSecs,aCurrentCharNumber);
+ return ETrue;
+ }
+
+ // If no character found, return EFalse
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDurSecondL
+// ---------------------------------------------------------------------------
+//
+/**
+Reads in and converts a dur-second into a number of seconds. There is no range
+check on the number of seconds.
+@param aIntervalSecs Function adds number of seconds to this variable.
+@param aCurrentCharNumber Character number to start looking in the value.
+@return ETrue if the value could be interpreted as a dur-second, EFalse
+otherwise.
+@internalTechnology
+*/
+TBool CESMRICalValue::GetDurSecondL(TInt& aIntervalSecs, TInt& aCurrentCharNumber) const
+ {
+ FUNC_LOG;
+
+ // dur-second = 1*DIGIT "S"
+
+ if (aCurrentCharNumber >= iValue->Length())
+ {
+ return EFalse;
+ }
+
+ // Create a new TPtrC containing the data from iValue which we need
+ TPtrC data(iValue->Mid(aCurrentCharNumber));
+
+ // Find the next 'S' in the descriptor
+ TInt nextSPos(data.Locate(KICalSecondChar));
+
+ // Check it exists
+ if (nextSPos != KErrNotFound)
+ {
+ // If character found, construct a number from currentCharNumber to nextSPos
+ TInt theNum(ReadIntL(data.Left(nextSPos)));
+
+ aIntervalSecs += theNum;
+ aCurrentCharNumber += nextSPos;
+
+ return ETrue;
+ }
+
+ // If no character found, return EFalse
+ return EFalse;
+ }
+
+// ---------------------------------------------------------------------------
+// CESMRICalValue::GetDurWeekL
+// ---------------------------------------------------------------------------
+//
+/**
+Reads in and converts a dur-week into a number of seconds
+@param aIntervalSecs Function adds number of seconds to this variable
+@param aCurrentCharNumber Character number to start looking in the value.
+@return ETrue if the value could be interpreted as a dur-week, EFalse
+otherwise.
+@internalTechnology
+*/
+TBool CESMRICalValue::GetDurWeekL(TInt& aIntervalSecs, TInt& aCurrentCharNumber) const
+ {
+ FUNC_LOG;
+
+ // dur-week = 1*DIGIT "W"
+
+ if (aCurrentCharNumber >= iValue->Length())
+ {
+ return EFalse;
+ }
+
+ // Create a new TPtrC containing the data from iValue which we need
+ TPtrC data(iValue->Mid(aCurrentCharNumber));
+
+ // Find the next 'W' in the descriptor
+ TInt nextWPos(data.Locate(KICalWeekChar));
+
+ // Check it exists
+ if (nextWPos != KErrNotFound)
+ {
+ // If character found, construct a number from currentCharNumber to nextWPos
+ TInt theNum(ReadIntL(data.Left(nextWPos)));
+
+ // Convert this time from weeks to seconds
+ theNum *= KICalSecondsPerWeek;
+
+ aIntervalSecs += theNum;
+ aCurrentCharNumber += nextWPos;
+
+ return ETrue;
+ }
+
+ // If no character found, return EFalse
+ return EFalse;
+ }
+
+
+// End of File
+
+
+