libraries/clogger/inc/SensibleFormat.h
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // SensibleFormat.h
       
     2 // 
       
     3 // Copyright (c) 2006 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "Eclipse Public License v1.0"
       
     6 // which accompanies this distribution, and is available
       
     7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 // 
       
     9 // Initial Contributors:
       
    10 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 // The purpose of this file is to define a generic format command that works reasonably even when there's no heap free
       
    14 // Because it uses a stack buffer in this case, it is very difficult to make this a generic function without macroing
       
    15 
       
    16 // Because I needed a 16-bit variant as well, and even templating would generate the same amount of code, I've done it
       
    17 // as a #includable code snippet
       
    18 
       
    19 // Note: If you do define SF_WIDE, Collapse() will be called on the result of the format before being passed to SF_ACTION
       
    20 
       
    21 // If you want to pass in a VA_LIST, then #define SF_LIST aArgList
       
    22 // If you want to pass in a bunch of arguments, #define SF_ARGLIST arg1,arg2,arg3
       
    23 
       
    24 #if !defined(SF_FORMAT) || !defined(SF_BUF) || !defined(SF_ACTION)
       
    25 #error "you must define all of SF_FORMAT, SF_BUF and SF_ACTION before including this file"
       
    26 #endif
       
    27 
       
    28 #if !((defined(SF_LIST) && !defined(SF_ARGLIST)) || (!defined(SF_LIST) && defined(SF_ARGLIST)))
       
    29 #error "you must define exactly one of SF_LIST and SF_ARGLIST before including this file"
       
    30 #endif
       
    31 
       
    32 #ifndef COMMON_H
       
    33 #error "you need to include common.h somewhere before including this file"
       
    34 #endif
       
    35 
       
    36 #ifdef SF_WIDE
       
    37 #define TOverflowX TOverflow16
       
    38 #define TBufX TBuf16<256>
       
    39 #else
       
    40 #define TOverflowX TOverflow8
       
    41 #define TBufX TBuf8<256>
       
    42 #endif
       
    43 
       
    44 #ifdef SF_ARGLIST
       
    45 #define SFAppend() AppendFormat(SF_FORMAT, &overflow, SF_ARGLIST)
       
    46 #else
       
    47 #define SFAppend() AppendFormatList(SF_FORMAT, SF_LIST, &overflow)
       
    48 #endif
       
    49 
       
    50 // Think of this as Format(RBuf8& SF_BUF, FunctionPointer SF_ACTION, const TDesCX& SF_FORMAT, TBool SF_STACKONLY, VA_LIST SF_LIST)
       
    51 // where SF_ACTION(SF_BUF) is called passing in the fully formatted string
       
    52 	{
       
    53 	const TInt minBufSize = Max(SF_BUF.MaxSize(), 512);
       
    54 	const TInt KMaxBufSize = 8192;
       
    55 	TInt err = KErrNone;
       
    56 
       
    57 #ifdef SF_STACKONLY
       
    58 	if (SF_STACKONLY)
       
    59 		{
       
    60 		err = KErrNoMemory;
       
    61 		}
       
    62 	else
       
    63 #endif
       
    64 		{
       
    65 		if (SF_BUF.MaxSize() == 0)
       
    66 			{
       
    67 			err = SF_BUF.Create(256);
       
    68 			}
       
    69 		else
       
    70 			{
       
    71 			SF_BUF.Zero();
       
    72 			}
       
    73 		}
       
    74 
       
    75 	TOverflowX overflow;
       
    76 	if (err == KErrNone)
       
    77 		{
       
    78 		// Do clever things to try and ensure that the format string won't be truncated, while at the same time not allocating an insanely big buffer
       
    79 		for (TInt bufSize = minBufSize; bufSize <= KMaxBufSize; bufSize*=2)
       
    80 			{
       
    81 			#ifdef SF_WIDE
       
    82 				TPtr16 widePtr((TUint16*)SF_BUF.Ptr(), SF_BUF.MaxSize()/2);
       
    83 				widePtr.SFAppend();
       
    84 			#else
       
    85 				SF_BUF.SFAppend();
       
    86 			#endif
       
    87 			if (!overflow.iOverflow)
       
    88 				{
       
    89 				// Then the format went ok
       
    90 				#ifdef SF_WIDE
       
    91 					TPtr8 collapsed = widePtr.Collapse();
       
    92 					SF_ACTION(collapsed);
       
    93 				#else
       
    94 					SF_ACTION(SF_BUF);
       
    95 				#endif
       
    96 				break;
       
    97 				}
       
    98 			else
       
    99 				{
       
   100 				// Overflowed
       
   101 
       
   102 				if (bufSize == KMaxBufSize)
       
   103 					{
       
   104 					// We've grown up to our (self-imposed) max buf size, so just live with the truncation
       
   105 					#ifdef SF_WIDE
       
   106 						TPtr8 collapsed = widePtr.Collapse();
       
   107 						SF_ACTION(collapsed);
       
   108 					#else
       
   109 						SF_ACTION(SF_BUF);
       
   110 					#endif
       
   111 					break;
       
   112 					}
       
   113 
       
   114 				// Try and grow
       
   115 				SF_BUF.Close();
       
   116 				err = SF_BUF.Create(bufSize*2);
       
   117 				if (err) break;
       
   118 				else continue;
       
   119 				}
       
   120 			}
       
   121 		}
       
   122 	if (err)
       
   123 		{
       
   124 		// Last resort, use 256 char buf on the stack
       
   125 		TBufX stackBuf;
       
   126 		stackBuf.SFAppend(); // Silently truncate if overflow happens now
       
   127 		#ifdef SF_WIDE
       
   128 			TPtr8 collapsed = stackBuf.Collapse();
       
   129 			SF_ACTION(collapsed);
       
   130 		#else
       
   131 			SF_ACTION(stackBuf);
       
   132 		#endif
       
   133 		}
       
   134 	}
       
   135 
       
   136 #undef SF_WIDE
       
   137 #undef SF_FORMAT
       
   138 #undef SF_LIST
       
   139 #undef SF_ARGLIST
       
   140 #undef SF_BUF
       
   141 #undef SF_ACTION
       
   142 #undef TBufX
       
   143 #undef TOverflowX
       
   144 #undef SFAppend
       
   145 #undef SF_STACKONLY