os/kernelhwsrv/kernel/eka/euser/us_des.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
parent 0 bde4ae8d615e
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\euser\us_des.cpp
    15 // 
    16 //
    17 
    18 #include "us_std.h"
    19 
    20 // Terrible hack. Surely we should use VA_START instead of the below?
    21 #if defined(__EABI__) || (defined(__X86__) && defined(__GCC32__))
    22 #define EABI_STYLE_VA_LISTS
    23 #endif
    24 
    25 const TInt KNoPrecision=-1;
    26 const TInt KDefaultPrecision=6;
    27 const TInt KMaxRealWidth=0x20;
    28 
    29 // TFormatedText8 and TFormatedText16
    30 
    31 class TFormatedText8
    32 	{
    33 public:
    34 	TBuf8<0x40> iBuffer;
    35 	const TUint8* iText;
    36 	TInt iTextLength;
    37 	TInt iWidth;
    38 	TAlign iJustify;
    39 	TChar iFill;
    40 	};
    41 
    42 class TFormatedText16
    43 	{
    44 public:
    45 	TBuf16<0x40> iBuffer;
    46 	const TUint16* iText;
    47 	TInt iTextLength;
    48 	TInt iWidth;
    49 	TAlign iJustify;
    50 	TChar iFill;
    51 	};
    52 
    53 // TPanicker8 and TPanicker16
    54 
    55 class TPanicker8
    56 	{
    57 public:
    58 	static inline void Panic_BadFormatDescriptor() {Panic(ETDes8BadFormatDescriptor);}
    59 	static inline void Panic_BadFormatParams() {Panic(ETDes8BadFormatParams);}
    60 	};
    61 
    62 class TPanicker16
    63 	{
    64 public:
    65 	static inline void Panic_BadFormatDescriptor() {Panic(ETDes16BadFormatDescriptor);}
    66 	static inline void Panic_BadFormatParams() {Panic(ETDes16BadFormatParams);}
    67 	};
    68 
    69 // TFormatDirective
    70 
    71 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
    72 	{
    73 public:
    74 	inline TFormatDirective() :iSizesOfParametersInBytes(0), iFormatDirectiveIndex(EImplicitFormatDirectiveIndex) {}
    75 	void AppendParameter(TInt aSizeOfParameterInBytes,TInt aParameterAlignment);
    76 	inline void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex) {iFormatDirectiveIndex=aFormatDirectiveIndex;}
    77 private:
    78 	friend class TParameterManager;
    79 private:
    80 	enum {EImplicitFormatDirectiveIndex=-1};
    81 	enum
    82 		{
    83 		EShiftToNumberOfParameters=28,
    84 		ENumberOfBitsPerParameter=5,
    85 		EMaskForSingleParameter=(1<<ENumberOfBitsPerParameter)-1,
    86 		EMaskForAlignmentShift=3,
    87 		EMaskForParameterSize=EMaskForSingleParameter&~EMaskForAlignmentShift,
    88 		EMaximumNumberOfParameters=EShiftToNumberOfParameters/ENumberOfBitsPerParameter
    89 		};
    90 private: // these functions are used by the TParameterManager class
    91 	inline TInt NumberOfParameters() const {return iSizesOfParametersInBytes>>EShiftToNumberOfParameters;}
    92 	TInt SizeOfParameter(TInt aIndex) const;
    93 	TUint8* CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const;
    94 private:
    95 	TUint iSizesOfParametersInBytes; // a compactly stored array
    96 	TInt iFormatDirectiveIndex;
    97 	};
    98 
    99 void TFormatDirective::AppendParameter(TInt aSizeOfParameterInBytes, TInt aParameterAlignment)
   100 	{
   101 	const TInt numberOfParameters=NumberOfParameters();
   102 	__ASSERT_DEBUG(numberOfParameters<EMaximumNumberOfParameters, Panic(ENumberOfParametersExceedsMaximum));
   103 	__ASSERT_DEBUG((aSizeOfParameterInBytes&EMaskForParameterSize)==aSizeOfParameterInBytes, Panic(ESizeOfParameterTooBig));
   104 	iSizesOfParametersInBytes+=(1<<EShiftToNumberOfParameters); // increment the count
   105 
   106 	switch(aParameterAlignment)
   107 		{
   108 	case 4:
   109 		// aSizeOfParameterInBytes |= 0;
   110 		break;
   111 	case 8:
   112 		aSizeOfParameterInBytes |= 1;
   113 		break;
   114 	default:
   115 		__ASSERT_DEBUG(0, Panic(EUnexpectedError3));
   116 		}
   117 
   118 	iSizesOfParametersInBytes|=(aSizeOfParameterInBytes<<(numberOfParameters*ENumberOfBitsPerParameter)); // store aSizeOfParameterInBytes
   119 	}
   120 
   121 TInt TFormatDirective::SizeOfParameter(TInt aIndex) const
   122 	{
   123 	__ASSERT_DEBUG(aIndex<NumberOfParameters(), Panic(EParameterIndexOutOfRange1));
   124 	return (iSizesOfParametersInBytes>>(aIndex*ENumberOfBitsPerParameter))&EMaskForParameterSize;
   125 	}
   126 
   127 TUint8* TFormatDirective::CalculateDataPointer(const TUint8* aDataPtr,TInt aIndex) const
   128 	{
   129 	TInt numParams = NumberOfParameters();
   130 	__ASSERT_DEBUG(aIndex<=numParams, Panic(EParameterIndexOutOfRange1));
   131 	TInt paramInfo = iSizesOfParametersInBytes;
   132 	while(numParams--)
   133 		{
   134 		TInt alignMask = (4<<(paramInfo&EMaskForAlignmentShift))-1;
   135 		aDataPtr = (TUint8*)(((TInt)aDataPtr+alignMask)&~alignMask);
   136 		if(!aIndex--)
   137 			break;
   138 		aDataPtr += paramInfo&EMaskForParameterSize;
   139 		paramInfo >>= ENumberOfBitsPerParameter;
   140 		}
   141 	return const_cast<TUint8*>(aDataPtr);
   142 	}
   143 
   144 // TParameterManager
   145 
   146 class TParameterManager
   147 	{
   148 public:
   149 	TParameterManager();
   150 	void AddFormatDirective(const TFormatDirective& aFormatDirective);
   151 	TInt PrepareToExtractNextParameter(VA_LIST aList); // returns either KErrNone or KErrNotReady
   152 	void PrepareToExtractParameters(VA_LIST aList);
   153 	TInt ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective);
   154 private:
   155 	enum
   156 		{
   157 		EMaximumNumberOfFormatDirectives=40,
   158 		ENumberOfBytesInBitArray=(EMaximumNumberOfFormatDirectives+7)/8
   159 		};
   160 private:
   161 	inline TBool FormatDirectiveIsSet(TInt aIndex) const {return iFormatDirectivesSet[aIndex/8]&(1<<(aIndex%8));}
   162 	inline void MarkFormatDirectiveAsSet(TInt aIndex) {iFormatDirectivesSet[aIndex/8]|=(1<<(aIndex%8)); __ASSERT_DEBUG(FormatDirectiveIsSet(aIndex), Panic(EFormatDirectiveAlreadySet1));}
   163 private:
   164 	TInt iNumberOfFormatDirectives;
   165 	TFixedArray<TUint8, ENumberOfBytesInBitArray> iFormatDirectivesSet;
   166 	TFixedArray<TFormatDirective, EMaximumNumberOfFormatDirectives> iFormatDirectives;
   167 	TFixedArray<const TUint8*, EMaximumNumberOfFormatDirectives> iFormatDirectiveDataPointers;
   168 	};
   169 
   170 TParameterManager::TParameterManager()
   171 	:iNumberOfFormatDirectives(0)
   172 	{
   173 	TInt i;
   174 	for (i=0; i<ENumberOfBytesInBitArray; ++i)
   175 		{
   176 		iFormatDirectivesSet[i]=0;
   177 		}
   178 	for (i=0; i<EMaximumNumberOfFormatDirectives; ++i)
   179 		{
   180 		iFormatDirectiveDataPointers[i]=NULL;
   181 		}
   182 	}
   183 
   184 void TParameterManager::AddFormatDirective(const TFormatDirective& aFormatDirective)
   185 	{
   186 	__ASSERT_ALWAYS(iNumberOfFormatDirectives<EMaximumNumberOfFormatDirectives, Panic(ENumberOfFormatDirectivesExceedsMaximum));
   187 	const TInt index=(aFormatDirective.iFormatDirectiveIndex>=0)? aFormatDirective.iFormatDirectiveIndex: iNumberOfFormatDirectives;
   188 	__ASSERT_ALWAYS(!FormatDirectiveIsSet(index), Panic(EFormatDirectiveAlreadySet2));
   189 	MarkFormatDirectiveAsSet(index);
   190 	iFormatDirectives[index]=aFormatDirective;
   191 	++iNumberOfFormatDirectives;
   192 	}
   193 
   194 TInt TParameterManager::PrepareToExtractNextParameter(VA_LIST aList)
   195 	{
   196 	if (iNumberOfFormatDirectives==0)
   197 		{
   198 #ifdef EABI_STYLE_VA_LISTS
   199 		// NB under the EABI we are passing va_list (a struct) by value. 
   200 		// We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI 
   201 		// extends to the name of the field. So I think the 'nasty' cast is likely to be more
   202 		// portable.
   203 		const TUint8 ** aL = (const TUint8**)&aList;
   204 		iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = aL[0];
   205 #else
   206 		// The horrible cast is there because you can't assume aList is of 'array' type   
   207 		iFormatDirectiveDataPointers[iNumberOfFormatDirectives] = (const TUint8*)(*(TInt*)aList);
   208 #endif
   209 		}
   210 	else
   211 		{
   212 		const TInt previousFormatDirective=iNumberOfFormatDirectives-1;
   213 		const TUint8* dataPointer=iFormatDirectiveDataPointers[previousFormatDirective];
   214 		if ((dataPointer==NULL) || !FormatDirectiveIsSet(previousFormatDirective))
   215 			{
   216 			return KErrNotReady;
   217 			}
   218 		const TFormatDirective& formatDirective=iFormatDirectives[previousFormatDirective];
   219 		dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters());
   220 		iFormatDirectiveDataPointers[iNumberOfFormatDirectives]=dataPointer;
   221 		}
   222 	return KErrNone;
   223 	}
   224 
   225 void TParameterManager::PrepareToExtractParameters(VA_LIST aList)
   226 	{
   227 #ifdef EABI_STYLE_VA_LISTS
   228 	// NB under the EABI we are passing va_list (a struct) by value. 
   229 	// We could extract the pointer using aList.__ap under RVCT, but I don't believe the EABI 
   230 	// extends to the name of the field. So I think the 'nasty' cast is likely to be more
   231 	// portable.
   232 	const TUint8 ** aL = (const TUint8**)&aList;
   233 	const TUint8* dataPointer = aL[0];
   234 #else
   235 	// The horrible cast is there because you can't assume aList is of 'array' type   
   236 	const TUint8* dataPointer = (const TUint8*)(*(TInt*)aList);
   237 #endif
   238 	if (iNumberOfFormatDirectives>0)
   239 		{
   240 		for (TInt i=0; ; ++i)
   241 			{
   242 			__ASSERT_ALWAYS(FormatDirectiveIsSet(i), Panic(EFormatDirectiveNotYetSet));
   243 			__ASSERT_DEBUG((iFormatDirectiveDataPointers[i]==NULL) || (iFormatDirectiveDataPointers[i]==dataPointer), Panic(EBadFormatDirectiveDataPointer));
   244 			iFormatDirectiveDataPointers[i]=dataPointer;
   245 			if (i+1>=iNumberOfFormatDirectives)
   246 				{
   247 				break;
   248 				}
   249 			const TFormatDirective& formatDirective=iFormatDirectives[i];
   250 			dataPointer = formatDirective.CalculateDataPointer(dataPointer,formatDirective.NumberOfParameters());
   251 			}
   252 		}
   253 	}
   254 
   255 TInt TParameterManager::ExtractParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aFormatDirectiveIndex, TInt aParameterIndexWithinFormatDirective, const TFormatDirective* aNextFormatDirective)
   256 	{
   257 	__ASSERT_DEBUG(aFormatDirectiveIndex<EMaximumNumberOfFormatDirectives, Panic(EFormatDirectiveIndexOutOfRange));
   258 	const TFormatDirective* formatDirective=NULL;
   259 	if (aFormatDirectiveIndex<iNumberOfFormatDirectives)
   260 		{
   261 		if (!FormatDirectiveIsSet(aFormatDirectiveIndex))
   262 			{
   263 			return KErrNotReady;
   264 			}
   265 		formatDirective=&iFormatDirectives[aFormatDirectiveIndex];
   266 		}
   267 	else
   268 		{
   269 		__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
   270 		if (aFormatDirectiveIndex>iNumberOfFormatDirectives)
   271 			{
   272 			return KErrNotReady;
   273 			}
   274 		formatDirective=aNextFormatDirective;
   275 		}
   276 	__ASSERT_DEBUG(aSizeOfParameterInBytes==formatDirective->SizeOfParameter(aParameterIndexWithinFormatDirective), Panic(EInconsistentSizeOfParameter));
   277 	const TUint8* dataPointer=iFormatDirectiveDataPointers[aFormatDirectiveIndex];
   278 	if (dataPointer==NULL)
   279 		{
   280 		__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
   281 		return KErrNotReady;
   282 		}
   283 	__ASSERT_DEBUG(aParameterIndexWithinFormatDirective<formatDirective->NumberOfParameters(), Panic(EParameterIndexOutOfRange2));
   284 	dataPointer = formatDirective->CalculateDataPointer(dataPointer,aParameterIndexWithinFormatDirective);
   285 	Mem::Copy(aTarget, dataPointer, aSizeOfParameterInBytes);
   286 	return KErrNone;
   287 	}
   288 
   289 // TParameterHandler
   290 
   291 class TParameterHandler
   292 	{
   293 public:
   294 	enum TAction
   295 		{
   296 		EParameterNotExtracted,
   297 		EParameterExtracted
   298 		};
   299 public:
   300 	inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager, TFormatDirective& aFormatDirective) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(&aFormatDirective), iParameterManager(aParameterManager) {} // for the first pass
   301 	inline TParameterHandler(TInt aImplicitFormatDirectiveIndex, TParameterManager& aParameterManager) :iFormatDirectiveIndex(aImplicitFormatDirectiveIndex), iParameterIndex(0), iFormatDirective(NULL), iParameterManager(aParameterManager) {} // for the second pass
   302 	TAction HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment=4);
   303 	void FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex);
   304 private:
   305 	TInt iFormatDirectiveIndex;
   306 	TInt iParameterIndex;
   307 	TFormatDirective* iFormatDirective;
   308 	TParameterManager& iParameterManager;
   309 	};
   310 
   311 TParameterHandler::TAction TParameterHandler::HandleParameter(TAny* aTarget, TInt aSizeOfParameterInBytes, TInt aParameterAlignment)
   312 // Increments iParameterIndex each time it is called.
   313 // 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.
   314 	{
   315 	__ASSERT_DEBUG(aTarget!=NULL, Panic(ENullTargetPointer));
   316 	__ASSERT_DEBUG(aSizeOfParameterInBytes>=0, Panic(ENegativeSizeOfParameter));
   317 	const TUint machineWordAlignmentConstant=sizeof(TUint)-1;
   318 	aSizeOfParameterInBytes+=machineWordAlignmentConstant;
   319 	aSizeOfParameterInBytes&=~machineWordAlignmentConstant;
   320 
   321 	if (iFormatDirective!=NULL)
   322 		{
   323 		iFormatDirective->AppendParameter(aSizeOfParameterInBytes,aParameterAlignment);
   324 		}
   325 	const TInt error=iParameterManager.ExtractParameter(aTarget, aSizeOfParameterInBytes, iFormatDirectiveIndex, iParameterIndex, iFormatDirective);
   326 #if defined(_DEBUG)
   327 	if (iFormatDirective==NULL) // if we're on the second pass...
   328 		{
   329 		__ASSERT_DEBUG(error==KErrNone, Panic(EErrorOnSecondPassOfFormatDescriptor));
   330 		}
   331 	else
   332 		{
   333 		__ASSERT_DEBUG(error==KErrNone || error==KErrNotReady, Panic(EUnexpectedError1));
   334 		}
   335 #endif
   336 	++iParameterIndex;
   337 	return (error==KErrNone)? EParameterExtracted: EParameterNotExtracted;
   338 	}
   339 
   340 void TParameterHandler::FormatDirectiveHasExplicitIndex(TInt aFormatDirectiveIndex)
   341 	{
   342 	if (iFormatDirective!=NULL)
   343 		{
   344 		iFormatDirective->FormatDirectiveHasExplicitIndex(aFormatDirectiveIndex);
   345 		}
   346 	iFormatDirectiveIndex=aFormatDirectiveIndex;
   347 	}
   348 
   349 template <class XDesC, class XFormatedText, class XLex, class XPanicker, TInt XItemSize>
   350 void HandleFormatDirective(TParameterHandler& aParameterHandler, XFormatedText& aFormatedText, XLex& aFmt)
   351 //
   352 // Handle a single format directive, i.e. sequence starting with a '%', (although the initial '%' will have been consumed by this point).
   353 //
   354 	{
   355 
   356 // Determine alignment of various types on the stack. The FOFF approach 
   357 // does not work for GCC 3.4.4 on X86 so we use hardcoded constants instead.
   358 #if defined(__GCC32__) && defined(__X86__) 
   359 	const TInt KAlignTReal = 4;
   360 	const TInt KAlignTRealX = 4;
   361 	const TInt KAlignTInt64 = 4;
   362 #else
   363  #ifndef __VC32__ // MSVC generates an internal compiler error with the following code
   364 	struct TReal_align {char c; TReal a;};
   365 	const TInt KAlignTReal = _FOFF(TReal_align,a);
   366 
   367 	struct TRealX_align {char c; TRealX a;};
   368 	const TInt KAlignTRealX = _FOFF(TRealX_align,a);
   369 
   370 	struct TInt64_align {char c; TInt64 a;};
   371 	const TInt KAlignTInt64 = _FOFF(TInt64_align,a);
   372  #else
   373 	//SL: Now also hardcoding KAlignTReal
   374 	const TInt KAlignTReal = 4;
   375 	const TInt KAlignTRealX = 4;	// Hard code value for MSVC
   376 	const TInt KAlignTInt64 = 4;	// Hard code value for MSVC
   377  #endif
   378 #endif
   379 
   380 	aFormatedText.iJustify=ERight; // Default is justify right
   381 	aFormatedText.iFill=KNoChar; // Default fill character is space
   382 	// After a % may come +,-,= or space
   383 	if (aFmt.Eos())
   384 		XPanicker::Panic_BadFormatDescriptor();
   385 	TChar c=aFmt.Get();
   386 
   387 	if (c=='$')
   388 		{
   389 		TInt formatDirectiveIndex;
   390 		if (aFmt.Val(formatDirectiveIndex)!=0)
   391 			XPanicker::Panic_BadFormatDescriptor();
   392 		aParameterHandler.FormatDirectiveHasExplicitIndex(formatDirectiveIndex-1);
   393 		if (aFmt.Get()!='$')
   394 			XPanicker::Panic_BadFormatDescriptor();
   395 		c=aFmt.Get();
   396 		}
   397 
   398 	switch (c)
   399 		{
   400 	case ' ':
   401 		aFormatedText.iFill=' ';
   402 		break;
   403 	case '-':
   404 		aFormatedText.iJustify=ELeft;
   405 		goto getFill;
   406 	case '=':
   407 		aFormatedText.iJustify=ECenter;
   408 		goto getFill;
   409 	case '+':
   410 getFill:
   411 		if (aFmt.Eos())
   412 			XPanicker::Panic_BadFormatDescriptor();
   413 		if (!aFmt.Peek().IsDigit())
   414 			{
   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
   416 			if (aFormatedText.iFill=='*') // If*  take it from the arguments
   417 				aParameterHandler.HandleParameter(&aFormatedText.iFill, sizeof(TUint));
   418 			}
   419 		break;
   420 	default:
   421 		aFmt.UnGet();
   422 		}
   423 
   424 	aFormatedText.iWidth=KDefaultJustifyWidth; // Default width is whatever the conversion takes
   425 	if (aFmt.Peek().IsDigit())
   426 		{
   427 		// If it starts with 0 and the fill character has not been
   428 		// specified then the fill character will be a 0
   429 		// For compatibility with standard C libraries
   430 		if (aFmt.Peek()=='0' && aFormatedText.iFill==KNoChar)
   431 			{
   432 			aFormatedText.iFill='0';
   433 			aFmt.Inc();
   434 			}
   435 		if (aFmt.Peek()!='*')
   436 			if (aFmt.Val(aFormatedText.iWidth)) // Convert field width value
   437 				XPanicker::Panic_BadFormatDescriptor();
   438 		}
   439 	if (aFmt.Peek()=='*' && aFormatedText.iWidth==KDefaultJustifyWidth) // If a * then get width from arguments
   440 		{
   441 		aParameterHandler.HandleParameter(&aFormatedText.iWidth, sizeof(TInt));
   442 		aFmt.Inc();
   443 		}
   444 	// Get precision setting if given
   445 	TInt precision=KNoPrecision;
   446 	if (aFmt.Peek()=='.')
   447 		{
   448 		aFmt.Inc();
   449 		if (aFmt.Peek()=='*')
   450 			{
   451 			aParameterHandler.HandleParameter(&precision, sizeof(TInt));
   452 			aFmt.Inc();
   453 			}
   454 		else if (aFmt.Val(precision))
   455 			XPanicker::Panic_BadFormatDescriptor();
   456 		}
   457 	if (aFormatedText.iFill==KNoChar) // If still default fill character make it space
   458 		aFormatedText.iFill=' ';
   459 	if (aFmt.Eos())
   460 		XPanicker::Panic_BadFormatDescriptor();
   461 	TChar selector;
   462 	TBool lng=EFalse;
   463 	TCharUC f=aFmt.Peek();
   464 	if (f=='L') // If l set selector for longs
   465 		{
   466 		aFmt.Inc();
   467 		lng=ETrue;
   468 		}
   469 	selector=aFmt.Get(); // Get the selector in upper case
   470 	aFormatedText.iText=aFormatedText.iBuffer.Ptr();
   471 	aFormatedText.iTextLength=1;
   472 	TRadix radix=EDecimal;
   473 	TUint uVal=0;
   474 	TReal rVal=0;
   475 	TRealX rValX=0;
   476 	TInt realFormatType=KRealFormatFixed;
   477 	switch (selector)
   478 		{
   479 	case 'S': // String conversion
   480 		{
   481 		const XDesC* pB;
   482 		if (aParameterHandler.HandleParameter(&pB, sizeof(const TAny*))==TParameterHandler::EParameterExtracted)
   483 			{
   484 			__ASSERT_DEBUG(pB!=0,XPanicker::Panic_BadFormatParams());
   485 			aFormatedText.iTextLength=pB->Length();
   486 			if (precision!=KNoPrecision && precision<aFormatedText.iTextLength)
   487 				aFormatedText.iTextLength=precision;
   488 			aFormatedText.iText=pB->Ptr();
   489 			}
   490 		}
   491 		break;
   492 	case 's':
   493 		if (aParameterHandler.HandleParameter(&aFormatedText.iText, sizeof(const TAny*))==TParameterHandler::EParameterExtracted)
   494 			{
   495 			__ASSERT_DEBUG(aFormatedText.iText!=0,XPanicker::Panic_BadFormatParams());
   496 			if (precision!=KNoPrecision)
   497 				aFormatedText.iTextLength=precision;
   498 			else
   499 				aFormatedText.iTextLength=User::StringLength(aFormatedText.iText);
   500 			}
   501 		break;
   502 	case 'O':
   503 	case 'o':
   504 		radix=EOctal;
   505 		goto lConv;
   506 	case 'X':
   507 	case 'x':
   508 		radix=EHex;
   509 		goto lConv;
   510 	case 'B': // Binary conversion
   511 	case 'b':
   512 		radix=EBinary;
   513 		// Fall-through to lConv
   514 	case 'U':
   515 	case 'u':
   516 lConv:
   517 		if (lng)
   518 			{
   519 			TInt64 uVal64 = 0;
   520 			if (aParameterHandler.HandleParameter(&uVal64, sizeof(TInt64), KAlignTInt64)==TParameterHandler::EParameterExtracted)
   521 				{
   522 				if (selector=='X')
   523 					aFormatedText.iBuffer.NumUC(uVal64,radix);
   524 				else
   525 					aFormatedText.iBuffer.Num(uVal64,radix);
   526 				}
   527 			}
   528 		else
   529 			{
   530 			if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
   531 				{
   532 				if (selector=='X')
   533 					aFormatedText.iBuffer.NumUC(uVal,radix);
   534 				else
   535 					aFormatedText.iBuffer.Num(uVal,radix);
   536 				}
   537 			}
   538 		aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
   539 		break;
   540 	case 'D': // Decimal conversion
   541 	case 'd':
   542 	case 'I':
   543 	case 'i':
   544 		if (lng)
   545 			{
   546 			TInt64 iVal64=0;
   547 			if (aParameterHandler.HandleParameter(&iVal64, sizeof(TInt64),KAlignTInt64)==TParameterHandler::EParameterExtracted)
   548 				{
   549 				aFormatedText.iBuffer.Num(iVal64);
   550 				}
   551 			}
   552 		else
   553 			{
   554 			TInt iVal=0;
   555 			if (aParameterHandler.HandleParameter(&iVal, sizeof(TInt))==TParameterHandler::EParameterExtracted)
   556 				{
   557 				aFormatedText.iBuffer.Num(iVal);
   558 				}
   559 			}
   560 		aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
   561 		break;
   562 	case 'P': // Padded conversion
   563 	case 'p':
   564 		aFormatedText.iTextLength=0;
   565 		break;
   566 	case 'C':
   567 	case 'c': // Ascii character conversion
   568 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))==TParameterHandler::EParameterExtracted)
   569 			{
   570 			aFormatedText.iBuffer.Append(uVal);
   571 			}
   572 		break;
   573 	case 'W': // SLONG binary lsb first conversion
   574 	case 'M': // SLONG binary msb first conversion
   575 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
   576 			{
   577 			break;
   578 			}
   579 		aFormatedText.iTextLength=4/XItemSize;
   580 		goto doBinary;
   581 	case 'w': // SWORD binary lsb first conversion
   582 	case 'm': // SWORD binary msb first conversion
   583 		if (aParameterHandler.HandleParameter(&uVal, sizeof(TUint))!=TParameterHandler::EParameterExtracted)
   584 			{
   585 			break;
   586 			}
   587 		aFormatedText.iTextLength=2/XItemSize;
   588 		//goto doBinary;
   589 doBinary:
   590 		{
   591 		TUint8* pC;
   592 		TInt increment;
   593 		if (selector=='m' || selector=='M')
   594 			{
   595 			pC=((TUint8*)(aFormatedText.iText+aFormatedText.iTextLength))-1;
   596 			increment=(-1);
   597 			}
   598 		else
   599 			{
   600 			pC=(TUint8*)aFormatedText.iText;
   601 			increment=1;
   602 			}
   603 		for (TInt k=aFormatedText.iTextLength*sizeof(*aFormatedText.iText);k>0;--k)
   604 			{
   605 			*pC=(TUint8)uVal;
   606 			pC+=increment;
   607 			uVal>>=8;
   608 			}
   609 		}
   610 		break;
   611 	case 'F': // TRealX conversion
   612 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
   613 			{
   614 			break;
   615 			}
   616 		rVal=rValX;
   617 		goto doReal;
   618 	case 'f': // TReal conversion
   619 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
   620 			{
   621 			break;
   622 			}
   623 		goto doReal;
   624 	case 'E':
   625 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
   626 			{
   627 			break;
   628 			}
   629 		rVal=rValX;
   630 		realFormatType=KRealFormatExponent|KAllowThreeDigitExp; 	// AnnW - changed from EExponent
   631 		goto doReal;
   632 	case 'e':
   633 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
   634 			{
   635 			break;
   636 			}
   637 		realFormatType=KRealFormatExponent|KAllowThreeDigitExp; 	// AnnW - changed from EExponent
   638 		//goto doReal;
   639 doReal:
   640 		{
   641 		if (precision==KNoPrecision)
   642 			precision=KDefaultPrecision;
   643 		TRealFormat realFormat(KMaxRealWidth, precision);
   644 		realFormat.iType=realFormatType;
   645 		aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
   646 		if (aFormatedText.iTextLength<0)
   647 			{
   648 			if (aFormatedText.iTextLength==KErrGeneral)
   649 				XPanicker::Panic_BadFormatDescriptor();
   650 			else
   651 				aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
   652 			}
   653 		if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
   654 			aFormatedText.iWidth=aFormatedText.iTextLength;
   655 		}
   656 		break;
   657 	case 'G':
   658 		if (aParameterHandler.HandleParameter(&rValX, sizeof(TRealX), KAlignTRealX)!=TParameterHandler::EParameterExtracted)
   659 			{
   660 			break;
   661 			}
   662 		rVal=rValX;
   663 		goto doGReal;
   664 	case 'g':
   665 		if (aParameterHandler.HandleParameter(&rVal, sizeof(TReal), KAlignTReal)!=TParameterHandler::EParameterExtracted)
   666 			{
   667 			break;
   668 			}
   669 		//goto doGReal;
   670 doGReal:
   671 		{
   672 		if (precision==KNoPrecision)
   673 			precision=KDefaultPrecision;
   674 
   675 		// aFormatedText.iBuffer must be >= KMaxRealWidth
   676 		TRealFormat realFormat(KMaxRealWidth, precision);	// Changed from 'width' to KMaxRealWidth
   677 		realFormat.iType=KRealFormatGeneral|KAllowThreeDigitExp;	// AnnW - changed from EGeneral
   678 		aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
   679 		if (aFormatedText.iTextLength<0)
   680 			{
   681 			// Doesn't fit in given width
   682 			realFormat.iWidth=KDefaultRealWidth;
   683 			aFormatedText.iTextLength=aFormatedText.iBuffer.Num(rVal, realFormat);
   684 			}
   685 		if (aFormatedText.iTextLength<0)
   686 			{
   687 			if (aFormatedText.iTextLength==KErrGeneral)
   688 				XPanicker::Panic_BadFormatDescriptor();
   689 			else
   690 				aFormatedText.iTextLength=aFormatedText.iBuffer.Length();
   691 			}
   692 		if (aFormatedText.iWidth!=KDefaultJustifyWidth && aFormatedText.iTextLength>aFormatedText.iWidth)
   693 			aFormatedText.iWidth=aFormatedText.iTextLength;
   694 		}
   695 		break;
   696 	default: // Not recognized - output % something
   697 		XPanicker::Panic_BadFormatDescriptor();
   698 		}
   699 	// Justify result of conversion
   700 	if (aFormatedText.iWidth==KDefaultJustifyWidth)
   701 		aFormatedText.iWidth=aFormatedText.iTextLength;
   702 	if (aFormatedText.iTextLength>aFormatedText.iWidth)
   703 		aFormatedText.iTextLength=aFormatedText.iWidth;
   704 	}
   705 
   706 template <class XDes, class XDesOverflow, class XDesC, class XFormatedText, class XLex, class XPanicker, TInt XItemSize>
   707 void DoAppendFormatList(XDes& aThis,const XDesC& aFormat,VA_LIST aList,XDesOverflow* aOverflowHandler)
   708 //
   709 // Convert the argument list, using the format descriptor.
   710 //
   711 	{
   712 
   713 	const TInt overflowLength=aOverflowHandler? aThis.MaxLength(): KMaxTInt;
   714 	const TInt originalLength=aThis.Length();
   715 	TBool needSecondPass=EFalse;
   716 	TParameterManager parameterManager;
   717 	XLex format(aFormat);
   718 	TInt implicitFormatDirectiveIndex=0;
   719 	FOREVER
   720 		{
   721 		if (format.Eos())
   722 			{
   723 			break;
   724 			}
   725 		const TChar character=format.Get();
   726 		if (character!='%')
   727 			{
   728 			if (!needSecondPass)
   729 				{
   730 				if (aThis.Length()>=overflowLength)
   731 					{
   732 					aOverflowHandler->Overflow(aThis);
   733 					return;
   734 					}
   735 				aThis.Append(character);
   736 				}
   737 			}
   738 		else if (format.Peek()=='%')
   739 			{
   740 			if (!needSecondPass)
   741 				{
   742 				if (aThis.Length()>=overflowLength)
   743 					{
   744 					aOverflowHandler->Overflow(aThis);
   745 					return;
   746 					}
   747 				aThis.Append(character);
   748 				}
   749 			format.Inc();
   750 			}
   751 		else
   752 			{
   753 			TFormatDirective formatDirective;
   754 			TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager, formatDirective);
   755 			XFormatedText formatedText;
   756 			const TInt error=parameterManager.PrepareToExtractNextParameter(aList);
   757 			if (error!=KErrNone)
   758 				{
   759 				__ASSERT_DEBUG(error==KErrNotReady, Panic(EUnexpectedError2));
   760 				needSecondPass=ETrue;
   761 				}
   762 			HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
   763 			parameterManager.AddFormatDirective(formatDirective);
   764 			if (!needSecondPass)
   765 				{
   766 				if ((aThis.Length()+formatedText.iWidth)>overflowLength)
   767 					{
   768 					aOverflowHandler->Overflow(aThis);
   769 					return;
   770 					}
   771 				aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
   772 				}
   773 			++implicitFormatDirectiveIndex;
   774 			}
   775 		}
   776 	if (needSecondPass)
   777 		{
   778 		aThis.SetLength(originalLength);
   779 		parameterManager.PrepareToExtractParameters(aList);
   780 		format=aFormat;
   781 		implicitFormatDirectiveIndex=0;
   782 		FOREVER
   783 			{
   784 			if (format.Eos())
   785 				{
   786 				break;
   787 				}
   788 			const TChar character=format.Get();
   789 			if (character!='%')
   790 				{
   791 				if (aThis.Length()>=overflowLength)
   792 					{
   793 					aOverflowHandler->Overflow(aThis);
   794 					return;
   795 					}
   796 				aThis.Append(character);
   797 				}
   798 			else if (format.Peek()=='%')
   799 				{
   800 				if (aThis.Length()>=overflowLength)
   801 					{
   802 					aOverflowHandler->Overflow(aThis);
   803 					return;
   804 					}
   805 				aThis.Append(character);
   806 				format.Inc();
   807 				}
   808 			else
   809 				{
   810 				TParameterHandler parameterHandler(implicitFormatDirectiveIndex, parameterManager);
   811 				XFormatedText formatedText;
   812 				HandleFormatDirective<XDesC, XFormatedText, XLex, XPanicker, XItemSize>(parameterHandler, formatedText, format);
   813 				if ((aThis.Length()+formatedText.iWidth)>overflowLength)
   814 					{
   815 					aOverflowHandler->Overflow(aThis);
   816 					return;
   817 					}
   818 				aThis.AppendJustify(formatedText.iText, formatedText.iTextLength, formatedText.iWidth, formatedText.iJustify, formatedText.iFill);
   819 				++implicitFormatDirectiveIndex;
   820 				}
   821 			}
   822 		}
   823 	}
   824 
   825 
   826 
   827 
   828 /**
   829 Formats and appends text onto the end of this descriptor's data.
   830 	
   831 The length of this descriptor is incremented to reflect the new content.
   832 	
   833 The behaviour of this function is the same as
   834 AppendFormat(TRefByValue<const TDesC8> aFmt,TDes8Overflow *aOverflowHandler,...).
   835 In practice, it is better and easier to use AppendFormat(), passing a variable number of 
   836 arguments as required by the format string.
   837 	
   838 @param aFormat          The descriptor containing the format string.
   839 @param aList            A pointer to an argument list.
   840 @param aOverflowHandler If supplied, a pointer to the overflow handler.
   841 
   842 @see TDes8::AppendFormat
   843 @see VA_LIST 
   844 */
   845 EXPORT_C void TDes8::AppendFormatList(const TDesC8 &aFormat,VA_LIST aList,TDes8Overflow *aOverflowHandler)
   846 	{
   847 
   848 	DoAppendFormatList<TDes8, TDes8Overflow, TDesC8, TFormatedText8, TLex8, TPanicker8, sizeof(TUint8)>(*this,aFormat,aList,aOverflowHandler);
   849 	}
   850 
   851 
   852 
   853 /**
   854 Formats and appends text onto the end of this descriptor's data.
   855 	
   856 The length of this descriptor is incremented to reflect the new content.
   857 	
   858 The behaviour of this function is the same as
   859 AppendFormat(TRefByValue<const TDesC16> aFmt,TDes16Overflow *aOverflowHandler,...).
   860 In practice, it is better and easier to use AppendFormat(), passing a variable number of 
   861 arguments as required by the format string.
   862 	
   863 @param aFormat          The descriptor containing the format string.
   864 @param aList            A pointer to an argument list.
   865 @param aOverflowHandler If supplied, a pointer to the overflow handler.
   866 
   867 @see TDes16::AppendFormat
   868 @see VA_LIST 
   869 */
   870 EXPORT_C void TDes16::AppendFormatList(const TDesC16 &aFormat,VA_LIST aList,TDes16Overflow *aOverflowHandler)
   871 	{
   872 
   873 	DoAppendFormatList<TDes16, TDes16Overflow, TDesC16, TFormatedText16, TLex16, TPanicker16, sizeof(TUint16)>(*this,aFormat,aList,aOverflowHandler);
   874 	}
   875