1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/us_des.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,872 @@
1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\euser\us_des.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "us_std.h"
1.22 +
1.23 +// Terrible hack. Surely we should use VA_START instead of the below?
1.24 +#if defined(__EABI__) || (defined(__X86__) && defined(__GCC32__))
1.25 +#define EABI_STYLE_VA_LISTS
1.26 +#endif
1.27 +
1.28 +const TInt KNoPrecision=-1;
1.29 +const TInt KDefaultPrecision=6;
1.30 +const TInt KMaxRealWidth=0x20;
1.31 +
1.32 +// TFormatedText8 and TFormatedText16
1.33 +
1.34 +class TFormatedText8
1.35 + {
1.36 +public:
1.37 + TBuf8<0x40> iBuffer;
1.38 + const TUint8* iText;
1.39 + TInt iTextLength;
1.40 + TInt iWidth;
1.41 + TAlign iJustify;
1.42 + TChar iFill;
1.43 + };
1.44 +
1.45 +class TFormatedText16
1.46 + {
1.47 +public:
1.48 + TBuf16<0x40> iBuffer;
1.49 + const TUint16* iText;
1.50 + TInt iTextLength;
1.51 + TInt iWidth;
1.52 + TAlign iJustify;
1.53 + TChar iFill;
1.54 + };
1.55 +
1.56 +// TPanicker8 and TPanicker16
1.57 +
1.58 +class TPanicker8
1.59 + {
1.60 +public:
1.61 + static inline void Panic_BadFormatDescriptor() {Panic(ETDes8BadFormatDescriptor);}
1.62 + static inline void Panic_BadFormatParams() {Panic(ETDes8BadFormatParams);}
1.63 + };
1.64 +
1.65 +class TPanicker16
1.66 + {
1.67 +public:
1.68 + static inline void Panic_BadFormatDescriptor() {Panic(ETDes16BadFormatDescriptor);}
1.69 + static inline void Panic_BadFormatParams() {Panic(ETDes16BadFormatParams);}
1.70 + };
1.71 +
1.72 +// TFormatDirective
1.73 +
1.74 +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
1.75 + {
1.76 +public:
1.77 + inline TFormatDirective() :iSizesOfParametersInBytes(0), iFormatDirectiveIndex(EImplicitFormatDirectiveIndex) {}
1.78 + void AppendParameter(TInt aSizeOfParameterInBytes,TInt aParameterAlignment);
1.79 + inline void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex) {iFormatDirectiveIndex=aFormatDirectiveIndex;}
1.80 +private:
1.81 + friend class TParameterManager;
1.82 +private:
1.83 + enum {EImplicitFormatDirectiveIndex=-1};
1.84 + enum
1.85 + {
1.86 + EShiftToNumberOfParameters=28,
1.87 + ENumberOfBitsPerParameter=5,
1.88 + EMaskForSingleParameter=(1<<ENumberOfBitsPerParameter)-1,
1.89 + EMaskForAlignmentShift=3,
1.90 + EMaskForParameterSize=EMaskForSingleParameter&~EMaskForAlignmentShift,
1.91 + EMaximumNumberOfParameters=EShiftToNumberOfParameters/ENumberOfBitsPerParameter
1.92 + };
1.93 +private: // these functions are used by the TParameterManager class
1.94 + inline TInt NumberOfParameters() const {return iSizesOfParametersInBytes>>EShiftToNumberOfParameters;}
1.95 + TInt SizeOfParameter(TInt aIndex) const;
1.96 + TUint8* CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const;
1.97 +private:
1.98 + TUint iSizesOfParametersInBytes; // a compactly stored array
1.99 + TInt iFormatDirectiveIndex;
1.100 + };
1.101 +
1.102 +void TFormatDirective::AppendParameter(TInt aSizeOfParameterInBytes, TInt aParameterAlignment)
1.103 + {
1.104 + const TInt numberOfParameters=NumberOfParameters();
1.105 + __ASSERT_DEBUG(numberOfParameters<EMaximumNumberOfParameters, Panic(ENumberOfParametersExceedsMaximum));
1.106 + __ASSERT_DEBUG((aSizeOfParameterInBytes&EMaskForParameterSize)==aSizeOfParameterInBytes, Panic(ESizeOfParameterTooBig));
1.107 + iSizesOfParametersInBytes+=(1<<EShiftToNumberOfParameters); // increment the count
1.108 +
1.109 + switch(aParameterAlignment)
1.110 + {
1.111 + case 4:
1.112 + // aSizeOfParameterInBytes |= 0;
1.113 + break;
1.114 + case 8:
1.115 + aSizeOfParameterInBytes |= 1;
1.116 + break;
1.117 + default:
1.118 + __ASSERT_DEBUG(0, Panic(EUnexpectedError3));
1.119 + }
1.120 +
1.121 + iSizesOfParametersInBytes|=(aSizeOfParameterInBytes<<(numberOfParameters*ENumberOfBitsPerParameter)); // store aSizeOfParameterInBytes
1.122 + }
1.123 +
1.124 +TInt TFormatDirective::SizeOfParameter(TInt aIndex) const
1.125 + {
1.126 + __ASSERT_DEBUG(aIndex<NumberOfParameters(), Panic(EParameterIndexOutOfRange1));
1.127 + return (iSizesOfParametersInBytes>>(aIndex*ENumberOfBitsPerParameter))&EMaskForParameterSize;
1.128 + }
1.129 +
1.130 +TUint8* TFormatDirective::CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const
1.131 + {
1.132 + TInt numParams = NumberOfParameters();
1.133 + __ASSERT_DEBUG(aIndex<=numParams, Panic(EParameterIndexOutOfRange1));
1.134 + TInt paramInfo = iSizesOfParametersInBytes;
1.135 + while(numParams--)
1.136 + {
1.137 + TInt alignMask = (4<<(paramInfo&EMaskForAlignmentShift))-1;
1.138 + aDataPtr = (TUint8*)(((TInt)aDataPtr+alignMask)&~alignMask);
1.139 + if(!aIndex--)
1.140 + break;
1.141 + aDataPtr += paramInfo&EMaskForParameterSize;
1.142 + paramInfo >>= ENumberOfBitsPerParameter;
1.143 + }
1.144 + return const_cast<TUint8*>(aDataPtr);
1.145 + }
1.146 +
1.147 +// TParameterManager
1.148 +
1.149 +class TParameterManager
1.150 + {
1.151 +public:
1.152 + TParameterManager();
1.153 + void AddFormatDirective(const TFormatDirective& aFormatDirective);
1.154 + TInt PrepareToExtractNextParameter(VA_LIST aList); // returns either KErrNone or KErrNotReady
1.155 + void PrepareToExtractParameters(VA_LIST aList);
1.156 + TInt ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective);
1.157 +private:
1.158 + enum
1.159 + {
1.160 + EMaximumNumberOfFormatDirectives=40,
1.161 + ENumberOfBytesInBitArray=(EMaximumNumberOfFormatDirectives+7)/8
1.162 + };
1.163 +private:
1.164 + inline TBool FormatDirectiveIsSet(TInt aIndex) const {return iFormatDirectivesSet[aIndex/8]&(1<<(aIndex%8));}
1.165 + inline void MarkFormatDirectiveAsSet(TInt aIndex) {iFormatDirectivesSet[aIndex/8]|=(1<<(aIndex%8)); __ASSERT_DEBUG(FormatDirectiveIsSet(aIndex), Panic(EFormatDirectiveAlreadySet1));}
1.166 +private:
1.167 + TInt iNumberOfFormatDirectives;
1.168 + TFixedArray<TUint8, ENumberOfBytesInBitArray> iFormatDirectivesSet;
1.169 + TFixedArray<TFormatDirective, EMaximumNumberOfFormatDirectives> iFormatDirectives;
1.170 + TFixedArray<const TUint8*, EMaximumNumberOfFormatDirectives> iFormatDirectiveDataPointers;
1.171 + };
1.172 +
1.173 +TParameterManager::TParameterManager()
1.174 + :iNumberOfFormatDirectives(0)
1.175 + {
1.176 + TInt i;
1.177 + for (i=0; i<ENumberOfBytesInBitArray; ++i)
1.178 + {
1.179 + iFormatDirectivesSet[i]=0;
1.180 + }
1.181 + for (i=0; i<EMaximumNumberOfFormatDirectives; ++i)
1.182 + {
1.183 + iFormatDirectiveDataPointers[i]=NULL;
1.184 + }
1.185 + }
1.186 +
1.187 +void TParameterManager::AddFormatDirective(const TFormatDirective& aFormatDirective)
1.188 + {
1.189 + __ASSERT_ALWAYS(iNumberOfFormatDirectives<EMaximumNumberOfFormatDirectives, Panic(ENumberOfFormatDirectivesExceedsMaximum));
1.190 + const TInt index=(aFormatDirective.iFormatDirectiveIndex>=0)? aFormatDirective.iFormatDirectiveIndex: iNumberOfFormatDirectives;
1.191 + __ASSERT_ALWAYS(!FormatDirectiveIsSet(index), Panic(EFormatDirectiveAlreadySet2));
1.192 + MarkFormatDirectiveAsSet(index);
1.193 + iFormatDirectives[index]=aFormatDirective;
1.194 + ++iNumberOfFormatDirectives;
1.195 + }
1.196 +
1.197 +TInt TParameterManager::PrepareToExtractNextParameter(VA_LIST aList)
1.198 + {
1.199 + if (iNumberOfFormatDirectives==0)
1.200 + {
1.201 +#ifdef EABI_STYLE_VA_LISTS
1.202 + // NB under the EABI we are passing va_list (a struct) by value.
1.203 + // We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI
1.204 + // extends to the name of the field. So I think the 'nasty' cast is likely to be more
1.205 + // portable.
1.206 + const TUint8 ** aL = (const TUint8**)&aList;
1.207 + iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = aL[0];
1.208 +#else
1.209 + // The horrible cast is there because you can't assume aList is of 'array' type
1.210 + iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = (const TUint8*)(*(TInt*)aList);
1.211 +#endif
1.212 + }
1.213 + else
1.214 + {
1.215 + const TInt previousFormatDirective=iNumberOfFormatDirectives-1;
1.216 + const TUint8* dataPointer=iFormatDirectiveDataPointers[previousFormatDirective];
1.217 + if ((dataPointer==NULL) || !FormatDirectiveIsSet(previousFormatDirective))
1.218 + {
1.219 + return KErrNotReady;
1.220 + }
1.221 + const TFormatDirective& formatDirective=iFormatDirectives[previousFormatDirective];
1.222 + dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters());
1.223 + iFormatDirectiveDataPointers[iNumberOfFormatDirectives]=dataPointer;
1.224 + }
1.225 + return KErrNone;
1.226 + }
1.227 +
1.228 +void TParameterManager::PrepareToExtractParameters(VA_LIST aList)
1.229 + {
1.230 +#ifdef EABI_STYLE_VA_LISTS
1.231 + // NB under the EABI we are passing va_list (a struct) by value.
1.232 + // We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI
1.233 + // extends to the name of the field. So I think the 'nasty' cast is likely to be more
1.234 + // portable.
1.235 + const TUint8 ** aL = (const TUint8**)&aList;
1.236 + const TUint8* dataPointer = aL[0];
1.237 +#else
1.238 + // The horrible cast is there because you can't assume aList is of 'array' type
1.239 + const TUint8* dataPointer = (const TUint8*)(*(TInt*)aList);
1.240 +#endif
1.241 + if (iNumberOfFormatDirectives>0)
1.242 + {
1.243 + for (TInt i=0; ; ++i)
1.244 + {
1.245 + __ASSERT_ALWAYS(FormatDirectiveIsSet(i), Panic(EFormatDirectiveNotYetSet));
1.246 + __ASSERT_DEBUG((iFormatDirectiveDataPointers[i]==NULL) || (iFormatDirectiveDataPointers[i]==dataPointer), Panic(EBadFormatDirectiveDataPointer));
1.247 + iFormatDirectiveDataPointers[i]=dataPointer;
1.248 + if (i+1>=iNumberOfFormatDirectives)
1.249 + {
1.250 + break;
1.251 + }
1.252 + const TFormatDirective& formatDirective=iFormatDirectives[i];
1.253 + dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters());
1.254 + }
1.255 + }
1.256 + }
1.257 +
1.258 +TInt TParameterManager::ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective)
1.259 + {
1.260 + __ASSERT_DEBUG(aFormatDirectiveIndex<EMaximumNumberOfFormatDirectives, Panic(EFormatDirectiveIndexOutOfRange));
1.261 + const TFormatDirective* formatDirective=NULL;
1.262 + if (aFormatDirectiveIndex<iNumberOfFormatDirectives)
1.263 + {
1.264 + if (!FormatDirectiveIsSet(aFormatDirectiveIndex))
1.265 + {
1.266 + return KErrNotReady;
1.267 + }
1.268 + formatDirective=&iFormatDirectives[aFormatDirectiveIndex];
1.269 + }
1.270 + else
1.271 + {
1.272 + __ASSERT_DEBUG(aNextFormatDirective!=NULL, Panic(ENotOnFirstPassOfFormatDescriptor1)); // the above condition (aFormatDirectiveIndex>=iNumberOfFormatDirectives) can only be the case on a first pass of the format descriptor, so assert that we're on the first pass
1.273 + if (aFormatDirectiveIndex>iNumberOfFormatDirectives)
1.274 + {
1.275 + return KErrNotReady;
1.276 + }
1.277 + formatDirective=aNextFormatDirective;
1.278 + }
1.279 + __ASSERT_DEBUG(aSizeOfParameterInBytes==formatDirective->SizeOfParameter(aParameterIndexWithinFormatDirective), Panic(EInconsistentSizeOfParameter));
1.280 + const TUint8* dataPointer=iFormatDirectiveDataPointers[aFormatDirectiveIndex];
1.281 + if (dataPointer==NULL)
1.282 + {
1.283 + __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
1.284 + return KErrNotReady;
1.285 + }
1.286 + __ASSERT_DEBUG(aParameterIndexWithinFormatDirective<formatDirective->NumberOfParameters(), Panic(EParameterIndexOutOfRange2));
1.287 + dataPointer = formatDirective->CalculateDataPointer(dataPointer,aParameterIndexWithinFormatDirective);
1.288 + Mem::Copy(aTarget, dataPointer, aSizeOfParameterInBytes);
1.289 + return KErrNone;
1.290 + }
1.291 +
1.292 +// TParameterHandler
1.293 +
1.294 +class TParameterHandler
1.295 + {
1.296 +public:
1.297 + enum TAction
1.298 + {
1.299 + EParameterNotExtracted,
1.300 + EParameterExtracted
1.301 + };
1.302 +public:
1.303 + inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager, TFormatDirective& aFormatDirective) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(&aFormatDirective), iParameterManager(aParameterManager) {} // for the first pass
1.304 + inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(NULL), iParameterManager(aParameterManager) {} // for the second pass
1.305 + TAction HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment=4);
1.306 + void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex);
1.307 +private:
1.308 + TInt iFormatDirectiveIndex;
1.309 + TInt iParameterIndex;
1.310 + TFormatDirective* iFormatDirective;
1.311 + TParameterManager& iParameterManager;
1.312 + };
1.313 +
1.314 +TParameterHandler::TAction TParameterHandler::HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment)
1.315 +// Increments iParameterIndex each time it is called.
1.316 +// 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.
1.317 + {
1.318 + __ASSERT_DEBUG(aTarget!=NULL, Panic(ENullTargetPointer));
1.319 + __ASSERT_DEBUG(aSizeOfParameterInBytes>=0, Panic(ENegativeSizeOfParameter));
1.320 + const TUint machineWordAlignmentConstant=sizeof(TUint)-1;
1.321 + aSizeOfParameterInBytes+=machineWordAlignmentConstant;
1.322 + aSizeOfParameterInBytes&=~machineWordAlignmentConstant;
1.323 +
1.324 + if (iFormatDirective!=NULL)
1.325 + {
1.326 + iFormatDirective->AppendParameter(aSizeOfParameterInBytes,aParameterAlignment);
1.327 + }
1.328 + const TInt error=iParameterManager.ExtractParameter(aTarget, aSizeOfParameterInBytes, iFormatDirectiveIndex, iParameterIndex, iFormatDirective);
1.329 +#if defined(_DEBUG)
1.330 + if (iFormatDirective==NULL) // if we're on the second pass...
1.331 + {
1.332 + __ASSERT_DEBUG(error==KErrNone, Panic(EErrorOnSecondPassOfFormatDescriptor));
1.333 + }
1.334 + else
1.335 + {
1.336 + __ASSERT_DEBUG(error==KErrNone || error==KErrNotReady, Panic(EUnexpectedError1));
1.337 + }
1.338 +#endif
1.339 + ++iParameterIndex;
1.340 + return (error==KErrNone)? EParameterExtracted: EParameterNotExtracted;
1.341 + }
1.342 +
1.343 +void TParameterHandler::FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex)
1.344 + {
1.345 + if (iFormatDirective!=NULL)
1.346 + {
1.347 + iFormatDirective->FormatDirectiveHasExplicitIndex(aFormatDirectiveIndex);
1.348 + }
1.349 + iFormatDirectiveIndex=aFormatDirectiveIndex;
1.350 + }
1.351 +
1.352 +template <class XDesC, class XFormatedText, class XLex, class XPanicker, TInt XItemSize>
1.353 +void HandleFormatDirective(TParameterHandler& aParameterHandler, XFormatedText& aFormatedText, XLex& aFmt)
1.354 +//
1.355 +// Handle a single format directive, i.e. sequence starting with a '%', (although the initial '%' will have been consumed by this point).
1.356 +//
1.357 + {
1.358 +
1.359 +// Determine alignment of various types on the stack. The FOFF approach
1.360 +// does not work for GCC 3.4.4 on X86 so we use hardcoded constants instead.
1.361 +#if defined(__GCC32__) && defined(__X86__)
1.362 + const TInt KAlignTReal = 4;
1.363 + const TInt KAlignTRealX = 4;
1.364 + const TInt KAlignTInt64 = 4;
1.365 +#else
1.366 + struct TReal_align {char c; TReal a;};
1.367 + const TInt KAlignTReal = _FOFF(TReal_align,a);
1.368 + #ifndef __VC32__ // MSVC generates an internal compiler error with the following code
1.369 + struct TRealX_align {char c; TRealX a;};
1.370 + const TInt KAlignTRealX = _FOFF(TRealX_align,a);
1.371 +
1.372 + struct TInt64_align {char c; TInt64 a;};
1.373 + const TInt KAlignTInt64 = _FOFF(TInt64_align,a);
1.374 + #else
1.375 + const TInt KAlignTRealX = 4; // Hard code value for MSVC
1.376 + const TInt KAlignTInt64 = 4; // Hard code value for MSVC
1.377 + #endif
1.378 +#endif
1.379 +
1.380 + aFormatedText.iJustify=ERight; // Default is justify right
1.381 + aFormatedText.iFill=KNoChar; // Default fill character is space
1.382 + // After a % may come +,-,= or space
1.383 + if (aFmt.Eos())
1.384 + XPanicker::Panic_BadFormatDescriptor();
1.385 + TChar c=aFmt.Get();
1.386 +
1.387 + if (c=='$')
1.388 + {
1.389 + TInt formatDirectiveIndex;
1.390 + if (aFmt.Val(formatDirectiveIndex)!=0)
1.391 + XPanicker::Panic_BadFormatDescriptor();
1.392 + aParameterHandler.FormatDirectiveHasExplicitIndex(formatDirectiveIndex-1);
1.393 + if (aFmt.Get()!='$')
1.394 + XPanicker::Panic_BadFormatDescriptor();
1.395 + c=aFmt.Get();
1.396 + }
1.397 +
1.398 + switch (c)
1.399 + {
1.400 + case ' ':
1.401 + aFormatedText.iFill=' ';
1.402 + break;
1.403 + case '-':
1.404 + aFormatedText.iJustify=ELeft;
1.405 + goto getFill;
1.406 + case '=':
1.407 + aFormatedText.iJustify=ECenter;
1.408 + goto getFill;
1.409 + case '+':
1.410 +getFill:
1.411 + if (aFmt.Eos())
1.412 + XPanicker::Panic_BadFormatDescriptor();
1.413 + if (!aFmt.Peek().IsDigit())
1.414 + {
1.415 + 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
1.416 + if (aFormatedText.iFill=='*') // If* take it from the arguments
1.417 + aParameterHandler.HandleParameter(&aFormatedText.iFill, sizeof(TUint));
1.418 + }
1.419 + break;
1.420 + default:
1.421 + aFmt.UnGet();
1.422 + }
1.423 +
1.424 + aFormatedText.iWidth=KDefaultJustifyWidth; // Default width is whatever the conversion takes
1.425 + if (aFmt.Peek().IsDigit())
1.426 + {
1.427 + // If it starts with 0 and the fill character has not been
1.428 + // specified then the fill character will be a 0
1.429 + // For compatibility with standard C libraries
1.430 + if (aFmt.Peek()=='0' && aFormatedText.iFill==KNoChar)
1.431 + {
1.432 + aFormatedText.iFill='0';
1.433 + aFmt.Inc();
1.434 + }
1.435 + if (aFmt.Peek()!='*')
1.436 + if (aFmt.Val(aFormatedText.iWidth)) // Convert field width value
1.437 + XPanicker::Panic_BadFormatDescriptor();
1.438 + }
1.439 + if (aFmt.Peek()=='*' && aFormatedText.iWidth==KDefaultJustifyWidth) // If a * then get width from arguments
1.440 + {
1.441 + aParameterHandler.HandleParameter(&aFormatedText.iWidth, sizeof(TInt));
1.442 + aFmt.Inc();
1.443 + }
1.444 + // Get precision setting if given
1.445 + TInt precision=KNoPrecision;
1.446 + if (aFmt.Peek()=='.')
1.447 + {
1.448 + aFmt.Inc();
1.449 + if (aFmt.Peek()=='*')
1.450 + {
1.451 + aParameterHandler.HandleParameter(&precision, sizeof(TInt));
1.452 + aFmt.Inc();
1.453 + }
1.454 + else if (aFmt.Val(precision))
1.455 + XPanicker::Panic_BadFormatDescriptor();
1.456 + }
1.457 + if (aFormatedText.iFill==KNoChar) // If still default fill character make it space
1.458 + aFormatedText.iFill=' ';
1.459 + if (aFmt.Eos())
1.460 + XPanicker::Panic_BadFormatDescriptor();
1.461 + TChar selector;
1.462 + TBool lng=EFalse;
1.463 + TCharUC f=aFmt.Peek();
1.464 + if (f=='L') // If l set selector for longs
1.465 + {
1.466 + aFmt.Inc();
1.467 + lng=ETrue;
1.468 + }
1.469 + selector=aFmt.Get(); // Get the selector in upper case
1.470 + aFormatedText.iText=aFormatedText.iBuffer.Ptr();
1.471 + aFormatedText.iTextLength=1;
1.472 + TRadix radix=EDecimal;
1.473 + TUint uVal=0;
1.474 + TReal rVal=0;
1.475 + TRealX rValX=0;
1.476 + TInt realFormatType=KRealFormatFixed;
1.477 + switch (selector)
1.478 + {
1.479 + case 'S': // String conversion
1.480 + {
1.481 + const XDesC* pB;
1.482 + if (aParameterHandler.HandleParameter(&pB, sizeof(const TAny*))==TParameterHandler::EParameterExtracted)
1.483 + {
1.484 + __ASSERT_DEBUG(pB!=0,XPanicker::Panic_BadFormatParams());
1.485 + aFormatedText.iTextLength=pB->Length();
1.486 + if (precision!=KNoPrecision && precision<aFormatedText.iTextLength)
1.487 + aFormatedText.iTextLength=precision;
1.488 + aFormatedText.iText=pB->Ptr();
1.489 + }
1.490 + }
1.491 + break;
1.492 + case 's':
1.493 + if (aParameterHandler.HandleParameter(&aFormatedText.iText, sizeof(const TAny*))==TParameterHandler::EParameterExtracted)
1.494 + {
1.495 + __ASSERT_DEBUG(aFormatedText.iText!=0,XPanicker::Panic_BadFormatParams());
1.496 + if (precision!=KNoPrecision)
1.497 + aFormatedText.iTextLength=precision;
1.498 + else
1.499 + aFormatedText.iTextLength=User::StringLength(aFormatedText.iText);
1.500 + }
1.501 + break;
1.502 + case 'O':
1.503 + case 'o':
1.504 + radix=EOctal;
1.505 + goto lConv;
1.506 + case 'X':
1.507 + case 'x':
1.508 + radix=EHex;
1.509 + goto lConv;
1.510 + case 'B': // Binary conversion
1.511 + case 'b':
1.512 + radix=EBinary;
1.513 + // Fall-through to lConv
1.514 + case 'U':
1.515 + case 'u':
1.516 +lConv:
1.517 + if (lng)
1.518 + {
1.519 + TInt64 uVal64 = 0;
1.520 + if (aParameterHandler.HandleParameter(&uVal64, sizeof(TInt64), KAlignTInt64)==TParameterHandler::EParameterExtracted)
1.521 + {
1.522 + if (selector=='X')
1.523 + aFormatedText.iBuffer.NumUC(uVal64,radix);
1.524 + else
1.525 + aFormatedText.iBuffer.Num(uVal64,radix);
1.526 + }
1.527 + }
1.528 + else
1.529 + {
1.530 + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
1.531 + {
1.532 + if (selector=='X')
1.533 + aFormatedText.iBuffer.NumUC(uVal,radix);
1.534 + else
1.535 + aFormatedText.iBuffer.Num(uVal,radix);
1.536 + }
1.537 + }
1.538 + aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
1.539 + break;
1.540 + case 'D': // Decimal conversion
1.541 + case 'd':
1.542 + case 'I':
1.543 + case 'i':
1.544 + if (lng)
1.545 + {
1.546 + TInt64 iVal64=0;
1.547 + if (aParameterHandler.HandleParameter(&iVal64, sizeof(TInt64),KAlignTInt64)==TParameterHandler::EParameterExtracted)
1.548 + {
1.549 + aFormatedText.iBuffer.Num(iVal64);
1.550 + }
1.551 + }
1.552 + else
1.553 + {
1.554 + TInt iVal=0;
1.555 + if (aParameterHandler.HandleParameter(&iVal, sizeof(TInt))==TParameterHandler::EParameterExtracted)
1.556 + {
1.557 + aFormatedText.iBuffer.Num(iVal);
1.558 + }
1.559 + }
1.560 + aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
1.561 + break;
1.562 + case 'P': // Padded conversion
1.563 + case 'p':
1.564 + aFormatedText.iTextLength=0;
1.565 + break;
1.566 + case 'C':
1.567 + case 'c': // Ascii character conversion
1.568 + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
1.569 + {
1.570 + aFormatedText.iBuffer.Append(uVal);
1.571 + }
1.572 + break;
1.573 + case 'W': // SLONG binary lsb first conversion
1.574 + case 'M': // SLONG binary msb first conversion
1.575 + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
1.576 + {
1.577 + break;
1.578 + }
1.579 + aFormatedText.iTextLength=4/XItemSize;
1.580 + goto doBinary;
1.581 + case 'w': // SWORD binary lsb first conversion
1.582 + case 'm': // SWORD binary msb first conversion
1.583 + if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
1.584 + {
1.585 + break;
1.586 + }
1.587 + aFormatedText.iTextLength=2/XItemSize;
1.588 + //goto doBinary;
1.589 +doBinary:
1.590 + {
1.591 + TUint8* pC;
1.592 + TInt increment;
1.593 + if (selector=='m' || selector=='M')
1.594 + {
1.595 + pC=((TUint8*)(aFormatedText.iText+aFormatedText.iTextLength))-1;
1.596 + increment=(-1);
1.597 + }
1.598 + else
1.599 + {
1.600 + pC=(TUint8*)aFormatedText.iText;
1.601 + increment=1;
1.602 + }
1.603 + for (TInt k=aFormatedText.iTextLength*sizeof(*aFormatedText.iText);k>0;--k)
1.604 + {
1.605 + *pC=(TUint8)uVal;
1.606 + pC+=increment;
1.607 + uVal>>=8;
1.608 + }
1.609 + }
1.610 + break;
1.611 + case 'F': // TRealX conversion
1.612 + if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
1.613 + {
1.614 + break;
1.615 + }
1.616 + rVal=rValX;
1.617 + goto doReal;
1.618 + case 'f': // TReal conversion
1.619 + if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
1.620 + {
1.621 + break;
1.622 + }
1.623 + goto doReal;
1.624 + case 'E':
1.625 + if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
1.626 + {
1.627 + break;
1.628 + }
1.629 + rVal=rValX;
1.630 + realFormatType=KRealFormatExponent|KAllowThreeDigitExp; // AnnW - changed from EExponent
1.631 + goto doReal;
1.632 + case 'e':
1.633 + if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
1.634 + {
1.635 + break;
1.636 + }
1.637 + realFormatType=KRealFormatExponent|KAllowThreeDigitExp; // AnnW - changed from EExponent
1.638 + //goto doReal;
1.639 +doReal:
1.640 + {
1.641 + if (precision==KNoPrecision)
1.642 + precision=KDefaultPrecision;
1.643 + TRealFormat realFormat(KMaxRealWidth, precision);
1.644 + realFormat.iType=realFormatType;
1.645 + aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
1.646 + if (aFormatedText.iTextLength<0)
1.647 + {
1.648 + if (aFormatedText.iTextLength==KErrGeneral)
1.649 + XPanicker::Panic_BadFormatDescriptor();
1.650 + else
1.651 + aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
1.652 + }
1.653 + if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
1.654 + aFormatedText.iWidth=aFormatedText.iTextLength;
1.655 + }
1.656 + break;
1.657 + case 'G':
1.658 + if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
1.659 + {
1.660 + break;
1.661 + }
1.662 + rVal=rValX;
1.663 + goto doGReal;
1.664 + case 'g':
1.665 + if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
1.666 + {
1.667 + break;
1.668 + }
1.669 + //goto doGReal;
1.670 +doGReal:
1.671 + {
1.672 + if (precision==KNoPrecision)
1.673 + precision=KDefaultPrecision;
1.674 +
1.675 + // aFormatedText.iBuffer must be >= KMaxRealWidth
1.676 + TRealFormat realFormat(KMaxRealWidth, precision); // Changed from 'width' to KMaxRealWidth
1.677 + realFormat.iType=KRealFormatGeneral|KAllowThreeDigitExp; // AnnW - changed from EGeneral
1.678 + aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
1.679 + if (aFormatedText.iTextLength<0)
1.680 + {
1.681 + // Doesn't fit in given width
1.682 + realFormat.iWidth=KDefaultRealWidth;
1.683 + aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
1.684 + }
1.685 + if (aFormatedText.iTextLength<0)
1.686 + {
1.687 + if (aFormatedText.iTextLength==KErrGeneral)
1.688 + XPanicker::Panic_BadFormatDescriptor();
1.689 + else
1.690 + aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
1.691 + }
1.692 + if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
1.693 + aFormatedText.iWidth=aFormatedText.iTextLength;
1.694 + }
1.695 + break;
1.696 + default: // Not recognized - output % something
1.697 + XPanicker::Panic_BadFormatDescriptor();
1.698 + }
1.699 + // Justify result of conversion
1.700 + if (aFormatedText.iWidth==KDefaultJustifyWidth)
1.701 + aFormatedText.iWidth=aFormatedText.iTextLength;
1.702 + if (aFormatedText.iTextLength>aFormatedText.iWidth)
1.703 + aFormatedText.iTextLength=aFormatedText.iWidth;
1.704 + }
1.705 +
1.706 +template <class XDes, class XDesOverflow, class XDesC, class XFormatedText, class XLex, class XPanicker, TInt XItemSize>
1.707 +void DoAppendFormatList(XDes& aThis,const XDesC& aFormat,VA_LIST aList,XDesOverflow* aOverflowHandler)
1.708 +//
1.709 +// Convert the argument list, using the format descriptor.
1.710 +//
1.711 + {
1.712 +
1.713 + const TInt overflowLength=aOverflowHandler? aThis.MaxLength(): KMaxTInt;
1.714 + const TInt originalLength=aThis.Length();
1.715 + TBool needSecondPass=EFalse;
1.716 + TParameterManager parameterManager;
1.717 + XLex format(aFormat);
1.718 + TInt implicitFormatDirectiveIndex=0;
1.719 + FOREVER
1.720 + {
1.721 + if (format.Eos())
1.722 + {
1.723 + break;
1.724 + }
1.725 + const TChar character=format.Get();
1.726 + if (character!='%')
1.727 + {
1.728 + if (!needSecondPass)
1.729 + {
1.730 + if (aThis.Length()>=overflowLength)
1.731 + {
1.732 + aOverflowHandler->Overflow(aThis);
1.733 + return;
1.734 + }
1.735 + aThis.Append(character);
1.736 + }
1.737 + }
1.738 + else if (format.Peek()=='%')
1.739 + {
1.740 + if (!needSecondPass)
1.741 + {
1.742 + if (aThis.Length()>=overflowLength)
1.743 + {
1.744 + aOverflowHandler->Overflow(aThis);
1.745 + return;
1.746 + }
1.747 + aThis.Append(character);
1.748 + }
1.749 + format.Inc();
1.750 + }
1.751 + else
1.752 + {
1.753 + TFormatDirective formatDirective;
1.754 + TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager, formatDirective);
1.755 + XFormatedText formatedText;
1.756 + const TInt error=parameterManager.PrepareToExtractNextParameter(aList);
1.757 + if (error!=KErrNone)
1.758 + {
1.759 + __ASSERT_DEBUG(error==KErrNotReady, Panic(EUnexpectedError2));
1.760 + needSecondPass=ETrue;
1.761 + }
1.762 + HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
1.763 + parameterManager.AddFormatDirective(formatDirective);
1.764 + if (!needSecondPass)
1.765 + {
1.766 + if ((aThis.Length()+formatedText.iWidth)>overflowLength)
1.767 + {
1.768 + aOverflowHandler->Overflow(aThis);
1.769 + return;
1.770 + }
1.771 + aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
1.772 + }
1.773 + ++implicitFormatDirectiveIndex;
1.774 + }
1.775 + }
1.776 + if (needSecondPass)
1.777 + {
1.778 + aThis.SetLength(originalLength);
1.779 + parameterManager.PrepareToExtractParameters(aList);
1.780 + format=aFormat;
1.781 + implicitFormatDirectiveIndex=0;
1.782 + FOREVER
1.783 + {
1.784 + if (format.Eos())
1.785 + {
1.786 + break;
1.787 + }
1.788 + const TChar character=format.Get();
1.789 + if (character!='%')
1.790 + {
1.791 + if (aThis.Length()>=overflowLength)
1.792 + {
1.793 + aOverflowHandler->Overflow(aThis);
1.794 + return;
1.795 + }
1.796 + aThis.Append(character);
1.797 + }
1.798 + else if (format.Peek()=='%')
1.799 + {
1.800 + if (aThis.Length()>=overflowLength)
1.801 + {
1.802 + aOverflowHandler->Overflow(aThis);
1.803 + return;
1.804 + }
1.805 + aThis.Append(character);
1.806 + format.Inc();
1.807 + }
1.808 + else
1.809 + {
1.810 + TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager);
1.811 + XFormatedText formatedText;
1.812 + HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
1.813 + if ((aThis.Length()+formatedText.iWidth)>overflowLength)
1.814 + {
1.815 + aOverflowHandler->Overflow(aThis);
1.816 + return;
1.817 + }
1.818 + aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
1.819 + ++implicitFormatDirectiveIndex;
1.820 + }
1.821 + }
1.822 + }
1.823 + }
1.824 +
1.825 +
1.826 +
1.827 +
1.828 +/**
1.829 +Formats and appends text onto the end of this descriptor's data.
1.830 +
1.831 +The length of this descriptor is incremented to reflect the new content.
1.832 +
1.833 +The behaviour of this function is the same as
1.834 +AppendFormat(TRefByValue<const TDesC8> aFmt,TDes8Overflow *aOverflowHandler,...).
1.835 +In practice, it is better and easier to use AppendFormat(), passing a variable number of
1.836 +arguments as required by the format string.
1.837 +
1.838 +@param aFormat The descriptor containing the format string.
1.839 +@param aList A pointer to an argument list.
1.840 +@param aOverflowHandler If supplied, a pointer to the overflow handler.
1.841 +
1.842 +@see TDes8::AppendFormat
1.843 +@see VA_LIST
1.844 +*/
1.845 +EXPORT_C void TDes8::AppendFormatList(const TDesC8 &aFormat,VA_LIST aList,TDes8Overflow *aOverflowHandler)
1.846 + {
1.847 +
1.848 + DoAppendFormatList<TDes8, TDes8Overflow, TDesC8, TFormatedText8, TLex8, TPanicker8, sizeof(TUint8)>(*this,aFormat,aList,aOverflowHandler);
1.849 + }
1.850 +
1.851 +
1.852 +
1.853 +/**
1.854 +Formats and appends text onto the end of this descriptor's data.
1.855 +
1.856 +The length of this descriptor is incremented to reflect the new content.
1.857 +
1.858 +The behaviour of this function is the same as
1.859 +AppendFormat(TRefByValue<const TDesC16> aFmt,TDes16Overflow *aOverflowHandler,...).
1.860 +In practice, it is better and easier to use AppendFormat(), passing a variable number of
1.861 +arguments as required by the format string.
1.862 +
1.863 +@param aFormat The descriptor containing the format string.
1.864 +@param aList A pointer to an argument list.
1.865 +@param aOverflowHandler If supplied, a pointer to the overflow handler.
1.866 +
1.867 +@see TDes16::AppendFormat
1.868 +@see VA_LIST
1.869 +*/
1.870 +EXPORT_C void TDes16::AppendFormatList(const TDesC16 &aFormat,VA_LIST aList,TDes16Overflow *aOverflowHandler)
1.871 + {
1.872 +
1.873 + DoAppendFormatList<TDes16, TDes16Overflow, TDesC16, TFormatedText16, TLex16, TPanicker16, sizeof(TUint16)>(*this,aFormat,aList,aOverflowHandler);
1.874 + }
1.875 +