diff -r c55016431358 -r 0a7b44b10206 symport/e32/euser/us_des.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symport/e32/euser/us_des.cpp Thu Jun 25 15:59:54 2009 +0100 @@ -0,0 +1,871 @@ +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Symbian Foundation License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// e32\euser\us_des.cpp +// +// + +#include "us_std.h" + +// Terrible hack. Surely we should use VA_START instead of the below? +#if defined(__EABI__) || (defined(__X86__) && defined(__GCC32__)) +#define EABI_STYLE_VA_LISTS +#endif + +const TInt KNoPrecision=-1; +const TInt KDefaultPrecision=6; +const TInt KMaxRealWidth=0x20; + +// TFormatedText8 and TFormatedText16 + +class TFormatedText8 + { +public: + TBuf8<0x40> iBuffer; + const TUint8* iText; + TInt iTextLength; + TInt iWidth; + TAlign iJustify; + TChar iFill; + }; + +class TFormatedText16 + { +public: + TBuf16<0x40> iBuffer; + const TUint16* iText; + TInt iTextLength; + TInt iWidth; + TAlign iJustify; + TChar iFill; + }; + +// TPanicker8 and TPanicker16 + +class TPanicker8 + { +public: + static inline void Panic_BadFormatDescriptor() {Panic(ETDes8BadFormatDescriptor);} + static inline void Panic_BadFormatParams() {Panic(ETDes8BadFormatParams);} + }; + +class TPanicker16 + { +public: + static inline void Panic_BadFormatDescriptor() {Panic(ETDes16BadFormatDescriptor);} + static inline void Panic_BadFormatParams() {Panic(ETDes16BadFormatParams);} + }; + +// TFormatDirective + +class TFormatDirective // basically a sort of array of parameters where the size of each parameter is stored (no more than 4 parameters are possible per format-directive) - it also knows whether the format directive it represents has an explicit index, and if so, what that index is + { +public: + inline TFormatDirective() :iSizesOfParametersInBytes(0), iFormatDirectiveIndex(EImplicitFormatDirectiveIndex) {} + void AppendParameter(TInt aSizeOfParameterInBytes,TInt aParameterAlignment); + inline void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex) {iFormatDirectiveIndex=aFormatDirectiveIndex;} +private: + friend class TParameterManager; +private: + enum {EImplicitFormatDirectiveIndex=-1}; + enum + { + EShiftToNumberOfParameters=28, + ENumberOfBitsPerParameter=5, + EMaskForSingleParameter=(1<>EShiftToNumberOfParameters;} + TInt SizeOfParameter(TInt aIndex) const; + TUint8* CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const; +private: + TUint iSizesOfParametersInBytes; // a compactly stored array + TInt iFormatDirectiveIndex; + }; + +void TFormatDirective::AppendParameter(TInt aSizeOfParameterInBytes, TInt aParameterAlignment) + { + const TInt numberOfParameters=NumberOfParameters(); + __ASSERT_DEBUG(numberOfParameters>(aIndex*ENumberOfBitsPerParameter))&EMaskForParameterSize; + } + +TUint8* TFormatDirective::CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const + { + TInt numParams = NumberOfParameters(); + __ASSERT_DEBUG(aIndex<=numParams, Panic(EParameterIndexOutOfRange1)); + TInt paramInfo = iSizesOfParametersInBytes; + while(numParams--) + { + TInt alignMask = (4<<(paramInfo&EMaskForAlignmentShift))-1; + aDataPtr = (TUint8*)(((TInt)aDataPtr+alignMask)&~alignMask); + if(!aIndex--) + break; + aDataPtr += paramInfo&EMaskForParameterSize; + paramInfo >>= ENumberOfBitsPerParameter; + } + return const_cast(aDataPtr); + } + +// TParameterManager + +class TParameterManager + { +public: + TParameterManager(); + void AddFormatDirective(const TFormatDirective& aFormatDirective); + TInt PrepareToExtractNextParameter(VA_LIST aList); // returns either KErrNone or KErrNotReady + void PrepareToExtractParameters(VA_LIST aList); + TInt ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective); +private: + enum + { + EMaximumNumberOfFormatDirectives=40, + ENumberOfBytesInBitArray=(EMaximumNumberOfFormatDirectives+7)/8 + }; +private: + inline TBool FormatDirectiveIsSet(TInt aIndex) const {return iFormatDirectivesSet[aIndex/8]&(1<<(aIndex%8));} + inline void MarkFormatDirectiveAsSet(TInt aIndex) {iFormatDirectivesSet[aIndex/8]|=(1<<(aIndex%8)); __ASSERT_DEBUG(FormatDirectiveIsSet(aIndex), Panic(EFormatDirectiveAlreadySet1));} +private: + TInt iNumberOfFormatDirectives; + TFixedArray iFormatDirectivesSet; + TFixedArray iFormatDirectives; + TFixedArray iFormatDirectiveDataPointers; + }; + +TParameterManager::TParameterManager() + :iNumberOfFormatDirectives(0) + { + TInt i; + for (i=0; i=0)? aFormatDirective.iFormatDirectiveIndex: iNumberOfFormatDirectives; + __ASSERT_ALWAYS(!FormatDirectiveIsSet(index), Panic(EFormatDirectiveAlreadySet2)); + MarkFormatDirectiveAsSet(index); + iFormatDirectives[index]=aFormatDirective; + ++iNumberOfFormatDirectives; + } + +TInt TParameterManager::PrepareToExtractNextParameter(VA_LIST aList) + { + if (iNumberOfFormatDirectives==0) + { +#ifdef EABI_STYLE_VA_LISTS + // NB under the EABI we are passing va_list (a struct) by value. + // We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI + // extends to the name of the field. So I think the 'nasty' cast is likely to be more + // portable. + const TUint8 ** aL = (const TUint8**)&aList; + iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = aL[0]; +#else + // The horrible cast is there because you can't assume aList is of 'array' type + iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = (const TUint8*)(*(TInt*)aList); +#endif + } + else + { + const TInt previousFormatDirective=iNumberOfFormatDirectives-1; + const TUint8* dataPointer=iFormatDirectiveDataPointers[previousFormatDirective]; + if ((dataPointer==NULL) || !FormatDirectiveIsSet(previousFormatDirective)) + { + return KErrNotReady; + } + const TFormatDirective& formatDirective=iFormatDirectives[previousFormatDirective]; + dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters()); + iFormatDirectiveDataPointers[iNumberOfFormatDirectives]=dataPointer; + } + return KErrNone; + } + +void TParameterManager::PrepareToExtractParameters(VA_LIST aList) + { +#ifdef EABI_STYLE_VA_LISTS + // NB under the EABI we are passing va_list (a struct) by value. + // We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI + // extends to the name of the field. So I think the 'nasty' cast is likely to be more + // portable. + const TUint8 ** aL = (const TUint8**)&aList; + const TUint8* dataPointer = aL[0]; +#else + // The horrible cast is there because you can't assume aList is of 'array' type + const TUint8* dataPointer = (const TUint8*)(*(TInt*)aList); +#endif + if (iNumberOfFormatDirectives>0) + { + for (TInt i=0; ; ++i) + { + __ASSERT_ALWAYS(FormatDirectiveIsSet(i), Panic(EFormatDirectiveNotYetSet)); + __ASSERT_DEBUG((iFormatDirectiveDataPointers[i]==NULL) || (iFormatDirectiveDataPointers[i]==dataPointer), Panic(EBadFormatDirectiveDataPointer)); + iFormatDirectiveDataPointers[i]=dataPointer; + if (i+1>=iNumberOfFormatDirectives) + { + break; + } + const TFormatDirective& formatDirective=iFormatDirectives[i]; + dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters()); + } + } + } + +TInt TParameterManager::ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective) + { + __ASSERT_DEBUG(aFormatDirectiveIndex=iNumberOfFormatDirectives) can only be the case on a first pass of the format descriptor, so assert that we're on the first pass + if (aFormatDirectiveIndex>iNumberOfFormatDirectives) + { + return KErrNotReady; + } + formatDirective=aNextFormatDirective; + } + __ASSERT_DEBUG(aSizeOfParameterInBytes==formatDirective->SizeOfParameter(aParameterIndexWithinFormatDirective), Panic(EInconsistentSizeOfParameter)); + const TUint8* dataPointer=iFormatDirectiveDataPointers[aFormatDirectiveIndex]; + if (dataPointer==NULL) + { + __ASSERT_DEBUG(aNextFormatDirective!=NULL, Panic(ENotOnFirstPassOfFormatDescriptor2)); // the above condition (dataPointer==NULL) can only be the case on a first pass of the format descriptor, so assert that we're on the first pass + return KErrNotReady; + } + __ASSERT_DEBUG(aParameterIndexWithinFormatDirectiveNumberOfParameters(), Panic(EParameterIndexOutOfRange2)); + dataPointer = formatDirective->CalculateDataPointer(dataPointer,aParameterIndexWithinFormatDirective); + Mem::Copy(aTarget, dataPointer, aSizeOfParameterInBytes); + return KErrNone; + } + +// TParameterHandler + +class TParameterHandler + { +public: + enum TAction + { + EParameterNotExtracted, + EParameterExtracted + }; +public: + inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager, TFormatDirective& aFormatDirective) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(&aFormatDirective), iParameterManager(aParameterManager) {} // for the first pass + inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(NULL), iParameterManager(aParameterManager) {} // for the second pass + TAction HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment=4); + void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex); +private: + TInt iFormatDirectiveIndex; + TInt iParameterIndex; + TFormatDirective* iFormatDirective; + TParameterManager& iParameterManager; + }; + +TParameterHandler::TAction TParameterHandler::HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment) +// Increments iParameterIndex each time it is called. +// This is conceptually a sort of virtual function (i.e. it's behaviour depends on the way the object was constructed), although it is not implemented like that. + { + __ASSERT_DEBUG(aTarget!=NULL, Panic(ENullTargetPointer)); + __ASSERT_DEBUG(aSizeOfParameterInBytes>=0, Panic(ENegativeSizeOfParameter)); + const TUint machineWordAlignmentConstant=sizeof(TUint)-1; + aSizeOfParameterInBytes+=machineWordAlignmentConstant; + aSizeOfParameterInBytes&=~machineWordAlignmentConstant; + + if (iFormatDirective!=NULL) + { + iFormatDirective->AppendParameter(aSizeOfParameterInBytes,aParameterAlignment); + } + const TInt error=iParameterManager.ExtractParameter(aTarget, aSizeOfParameterInBytes, iFormatDirectiveIndex, iParameterIndex, iFormatDirective); +#if defined(_DEBUG) + if (iFormatDirective==NULL) // if we're on the second pass... + { + __ASSERT_DEBUG(error==KErrNone, Panic(EErrorOnSecondPassOfFormatDescriptor)); + } + else + { + __ASSERT_DEBUG(error==KErrNone || error==KErrNotReady, Panic(EUnexpectedError1)); + } +#endif + ++iParameterIndex; + return (error==KErrNone)? EParameterExtracted: EParameterNotExtracted; + } + +void TParameterHandler::FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex) + { + if (iFormatDirective!=NULL) + { + iFormatDirective->FormatDirectiveHasExplicitIndex(aFormatDirectiveIndex); + } + iFormatDirectiveIndex=aFormatDirectiveIndex; + } + +template +void HandleFormatDirective(TParameterHandler& aParameterHandler, XFormatedText& aFormatedText, XLex& aFmt) +// +// Handle a single format directive, i.e. sequence starting with a '%', (although the initial '%' will have been consumed by this point). +// + { + +// Determine alignment of various types on the stack. The FOFF approach +// does not work for GCC 3.4.4 on X86 so we use hardcoded constants instead. +#if defined(__GCC32__) && defined(__X86__) + const TInt KAlignTReal = 4; + const TInt KAlignTRealX = 4; + const TInt KAlignTInt64 = 4; +#else + struct TReal_align {char c; TReal a;}; + const TInt KAlignTReal = _FOFF(TReal_align,a); + #ifndef __VC32__ // MSVC generates an internal compiler error with the following code + struct TRealX_align {char c; TRealX a;}; + const TInt KAlignTRealX = _FOFF(TRealX_align,a); + + struct TInt64_align {char c; TInt64 a;}; + const TInt KAlignTInt64 = _FOFF(TInt64_align,a); + #else + const TInt KAlignTRealX = 4; // Hard code value for MSVC + const TInt KAlignTInt64 = 4; // Hard code value for MSVC + #endif +#endif + + aFormatedText.iJustify=ERight; // Default is justify right + aFormatedText.iFill=KNoChar; // Default fill character is space + // After a % may come +,-,= or space + if (aFmt.Eos()) + XPanicker::Panic_BadFormatDescriptor(); + TChar c=aFmt.Get(); + + if (c=='$') + { + TInt formatDirectiveIndex; + if (aFmt.Val(formatDirectiveIndex)!=0) + XPanicker::Panic_BadFormatDescriptor(); + aParameterHandler.FormatDirectiveHasExplicitIndex(formatDirectiveIndex-1); + if (aFmt.Get()!='$') + XPanicker::Panic_BadFormatDescriptor(); + c=aFmt.Get(); + } + + switch (c) + { + case ' ': + aFormatedText.iFill=' '; + break; + case '-': + aFormatedText.iJustify=ELeft; + goto getFill; + case '=': + aFormatedText.iJustify=ECenter; + goto getFill; + case '+': +getFill: + if (aFmt.Eos()) + XPanicker::Panic_BadFormatDescriptor(); + if (!aFmt.Peek().IsDigit()) + { + aFormatedText.iFill=aFmt.Get(); // assigning aFormatedText.iFill to something other than KNoChar is necessary as the aParameterHandler.HandleParameter call a couple of lines below will not necessarily set its first parameter (i.e. aFormatedText.iFill) - aFormatedText.iFill is tested against KNoChar ten or so lines below + if (aFormatedText.iFill=='*') // If* take it from the arguments + aParameterHandler.HandleParameter(&aFormatedText.iFill, sizeof(TUint)); + } + break; + default: + aFmt.UnGet(); + } + + aFormatedText.iWidth=KDefaultJustifyWidth; // Default width is whatever the conversion takes + if (aFmt.Peek().IsDigit()) + { + // If it starts with 0 and the fill character has not been + // specified then the fill character will be a 0 + // For compatibility with standard C libraries + if (aFmt.Peek()=='0' && aFormatedText.iFill==KNoChar) + { + aFormatedText.iFill='0'; + aFmt.Inc(); + } + if (aFmt.Peek()!='*') + if (aFmt.Val(aFormatedText.iWidth)) // Convert field width value + XPanicker::Panic_BadFormatDescriptor(); + } + if (aFmt.Peek()=='*' && aFormatedText.iWidth==KDefaultJustifyWidth) // If a * then get width from arguments + { + aParameterHandler.HandleParameter(&aFormatedText.iWidth, sizeof(TInt)); + aFmt.Inc(); + } + // Get precision setting if given + TInt precision=KNoPrecision; + if (aFmt.Peek()=='.') + { + aFmt.Inc(); + if (aFmt.Peek()=='*') + { + aParameterHandler.HandleParameter(&precision, sizeof(TInt)); + aFmt.Inc(); + } + else if (aFmt.Val(precision)) + XPanicker::Panic_BadFormatDescriptor(); + } + if (aFormatedText.iFill==KNoChar) // If still default fill character make it space + aFormatedText.iFill=' '; + if (aFmt.Eos()) + XPanicker::Panic_BadFormatDescriptor(); + TChar selector; + TBool lng=EFalse; + TCharUC f=aFmt.Peek(); + if (f=='L') // If l set selector for longs + { + aFmt.Inc(); + lng=ETrue; + } + selector=aFmt.Get(); // Get the selector in upper case + aFormatedText.iText=aFormatedText.iBuffer.Ptr(); + aFormatedText.iTextLength=1; + TRadix radix=EDecimal; + TUint uVal=0; + TReal rVal=0; + TRealX rValX=0; + TInt realFormatType=KRealFormatFixed; + switch (selector) + { + case 'S': // String conversion + { + const XDesC* pB; + if (aParameterHandler.HandleParameter(&pB, sizeof(const TAny*))==TParameterHandler::EParameterExtracted) + { + __ASSERT_DEBUG(pB!=0,XPanicker::Panic_BadFormatParams()); + aFormatedText.iTextLength=pB->Length(); + if (precision!=KNoPrecision && precisionPtr(); + } + } + break; + case 's': + if (aParameterHandler.HandleParameter(&aFormatedText.iText, sizeof(const TAny*))==TParameterHandler::EParameterExtracted) + { + __ASSERT_DEBUG(aFormatedText.iText!=0,XPanicker::Panic_BadFormatParams()); + if (precision!=KNoPrecision) + aFormatedText.iTextLength=precision; + else + aFormatedText.iTextLength=User::StringLength(aFormatedText.iText); + } + break; + case 'O': + case 'o': + radix=EOctal; + goto lConv; + case 'X': + case 'x': + radix=EHex; + goto lConv; + case 'B': // Binary conversion + case 'b': + radix=EBinary; + case 'U': + case 'u': +lConv: + if (lng) + { + TInt64 uVal64 = 0; + if (aParameterHandler.HandleParameter(&uVal64, sizeof(TInt64), KAlignTInt64)==TParameterHandler::EParameterExtracted) + { + if (selector=='X') + aFormatedText.iBuffer.NumUC(uVal64,radix); + else + aFormatedText.iBuffer.Num(uVal64,radix); + } + } + else + { + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted) + { + if (selector=='X') + aFormatedText.iBuffer.NumUC(uVal,radix); + else + aFormatedText.iBuffer.Num(uVal,radix); + } + } + aFormatedText.iTextLength=aFormatedText.iBuffer.Length(); + break; + case 'D': // Decimal conversion + case 'd': + case 'I': + case 'i': + if (lng) + { + TInt64 iVal64=0; + if (aParameterHandler.HandleParameter(&iVal64, sizeof(TInt64),KAlignTInt64)==TParameterHandler::EParameterExtracted) + { + aFormatedText.iBuffer.Num(iVal64); + } + } + else + { + TInt iVal=0; + if (aParameterHandler.HandleParameter(&iVal, sizeof(TInt))==TParameterHandler::EParameterExtracted) + { + aFormatedText.iBuffer.Num(iVal); + } + } + aFormatedText.iTextLength=aFormatedText.iBuffer.Length(); + break; + case 'P': // Padded conversion + case 'p': + aFormatedText.iTextLength=0; + break; + case 'C': + case 'c': // Ascii character conversion + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted) + { + aFormatedText.iBuffer.Append(uVal); + } + break; + case 'W': // SLONG binary lsb first conversion + case 'M': // SLONG binary msb first conversion + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted) + { + break; + } + aFormatedText.iTextLength=4/XItemSize; + goto doBinary; + case 'w': // SWORD binary lsb first conversion + case 'm': // SWORD binary msb first conversion + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted) + { + break; + } + aFormatedText.iTextLength=2/XItemSize; + //goto doBinary; +doBinary: + { + TUint8* pC; + TInt increment; + if (selector=='m' || selector=='M') + { + pC=((TUint8*)(aFormatedText.iText+aFormatedText.iTextLength))-1; + increment=(-1); + } + else + { + pC=(TUint8*)aFormatedText.iText; + increment=1; + } + for (TInt k=aFormatedText.iTextLength*sizeof(*aFormatedText.iText);k>0;--k) + { + *pC=(TUint8)uVal; + pC+=increment; + uVal>>=8; + } + } + break; + case 'F': // TRealX conversion + if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted) + { + break; + } + rVal=rValX; + goto doReal; + case 'f': // TReal conversion + if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted) + { + break; + } + goto doReal; + case 'E': + if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted) + { + break; + } + rVal=rValX; + realFormatType=KRealFormatExponent|KAllowThreeDigitExp; // AnnW - changed from EExponent + goto doReal; + case 'e': + if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted) + { + break; + } + realFormatType=KRealFormatExponent|KAllowThreeDigitExp; // AnnW - changed from EExponent + //goto doReal; +doReal: + { + if (precision==KNoPrecision) + precision=KDefaultPrecision; + TRealFormat realFormat(KMaxRealWidth, precision); + realFormat.iType=realFormatType; + aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat); + if (aFormatedText.iTextLength<0) + { + if (aFormatedText.iTextLength==KErrGeneral) + XPanicker::Panic_BadFormatDescriptor(); + else + aFormatedText.iTextLength=aFormatedText.iBuffer.Length(); + } + if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth) + aFormatedText.iWidth=aFormatedText.iTextLength; + } + break; + case 'G': + if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted) + { + break; + } + rVal=rValX; + goto doGReal; + case 'g': + if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted) + { + break; + } + //goto doGReal; +doGReal: + { + if (precision==KNoPrecision) + precision=KDefaultPrecision; + + // aFormatedText.iBuffer must be >= KMaxRealWidth + TRealFormat realFormat(KMaxRealWidth, precision); // Changed from 'width' to KMaxRealWidth + realFormat.iType=KRealFormatGeneral|KAllowThreeDigitExp; // AnnW - changed from EGeneral + aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat); + if (aFormatedText.iTextLength<0) + { + // Doesn't fit in given width + realFormat.iWidth=KDefaultRealWidth; + aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat); + } + if (aFormatedText.iTextLength<0) + { + if (aFormatedText.iTextLength==KErrGeneral) + XPanicker::Panic_BadFormatDescriptor(); + else + aFormatedText.iTextLength=aFormatedText.iBuffer.Length(); + } + if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth) + aFormatedText.iWidth=aFormatedText.iTextLength; + } + break; + default: // Not recognized - output % something + XPanicker::Panic_BadFormatDescriptor(); + } + // Justify result of conversion + if (aFormatedText.iWidth==KDefaultJustifyWidth) + aFormatedText.iWidth=aFormatedText.iTextLength; + if (aFormatedText.iTextLength>aFormatedText.iWidth) + aFormatedText.iTextLength=aFormatedText.iWidth; + } + +template +void DoAppendFormatList(XDes& aThis,const XDesC& aFormat,VA_LIST aList,XDesOverflow* aOverflowHandler) +// +// Convert the argument list, using the format descriptor. +// + { + + const TInt overflowLength=aOverflowHandler? aThis.MaxLength(): KMaxTInt; + const TInt originalLength=aThis.Length(); + TBool needSecondPass=EFalse; + TParameterManager parameterManager; + XLex format(aFormat); + TInt implicitFormatDirectiveIndex=0; + FOREVER + { + if (format.Eos()) + { + break; + } + const TChar character=format.Get(); + if (character!='%') + { + if (!needSecondPass) + { + if (aThis.Length()>=overflowLength) + { + aOverflowHandler->Overflow(aThis); + return; + } + aThis.Append(character); + } + } + else if (format.Peek()=='%') + { + if (!needSecondPass) + { + if (aThis.Length()>=overflowLength) + { + aOverflowHandler->Overflow(aThis); + return; + } + aThis.Append(character); + } + format.Inc(); + } + else + { + TFormatDirective formatDirective; + TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager, formatDirective); + XFormatedText formatedText; + const TInt error=parameterManager.PrepareToExtractNextParameter(aList); + if (error!=KErrNone) + { + __ASSERT_DEBUG(error==KErrNotReady, Panic(EUnexpectedError2)); + needSecondPass=ETrue; + } + HandleFormatDirective(parameterHandler, formatedText, format); + parameterManager.AddFormatDirective(formatDirective); + if (!needSecondPass) + { + if ((aThis.Length()+formatedText.iWidth)>overflowLength) + { + aOverflowHandler->Overflow(aThis); + return; + } + aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill); + } + ++implicitFormatDirectiveIndex; + } + } + if (needSecondPass) + { + aThis.SetLength(originalLength); + parameterManager.PrepareToExtractParameters(aList); + format=aFormat; + implicitFormatDirectiveIndex=0; + FOREVER + { + if (format.Eos()) + { + break; + } + const TChar character=format.Get(); + if (character!='%') + { + if (aThis.Length()>=overflowLength) + { + aOverflowHandler->Overflow(aThis); + return; + } + aThis.Append(character); + } + else if (format.Peek()=='%') + { + if (aThis.Length()>=overflowLength) + { + aOverflowHandler->Overflow(aThis); + return; + } + aThis.Append(character); + format.Inc(); + } + else + { + TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager); + XFormatedText formatedText; + HandleFormatDirective(parameterHandler, formatedText, format); + if ((aThis.Length()+formatedText.iWidth)>overflowLength) + { + aOverflowHandler->Overflow(aThis); + return; + } + aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill); + ++implicitFormatDirectiveIndex; + } + } + } + } + + + + +/** +Formats and appends text onto the end of this descriptor's data. + +The length of this descriptor is incremented to reflect the new content. + +The behaviour of this function is the same as +AppendFormat(TRefByValue aFmt,TDes8Overflow *aOverflowHandler,...). +In practice, it is better and easier to use AppendFormat(), passing a variable number of +arguments as required by the format string. + +@param aFormat The descriptor containing the format string. +@param aList A pointer to an argument list. +@param aOverflowHandler If supplied, a pointer to the overflow handler. + +@see TDes8::AppendFormat +@see VA_LIST +*/ +EXPORT_C void TDes8::AppendFormatList(const TDesC8 &aFormat,VA_LIST aList,TDes8Overflow *aOverflowHandler) + { + + DoAppendFormatList(*this,aFormat,aList,aOverflowHandler); + } + + + +/** +Formats and appends text onto the end of this descriptor's data. + +The length of this descriptor is incremented to reflect the new content. + +The behaviour of this function is the same as +AppendFormat(TRefByValue aFmt,TDes16Overflow *aOverflowHandler,...). +In practice, it is better and easier to use AppendFormat(), passing a variable number of +arguments as required by the format string. + +@param aFormat The descriptor containing the format string. +@param aList A pointer to an argument list. +@param aOverflowHandler If supplied, a pointer to the overflow handler. + +@see TDes16::AppendFormat +@see VA_LIST +*/ +EXPORT_C void TDes16::AppendFormatList(const TDesC16 &aFormat,VA_LIST aList,TDes16Overflow *aOverflowHandler) + { + + DoAppendFormatList(*this,aFormat,aList,aOverflowHandler); + } +