diff -r 000000000000 -r 8466d47a6819 meetingrequest/mrversit2/src/cesmricalvalue.cpp --- /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(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& 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 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(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 + + +