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