libraries/clogger/inc/SensibleFormat.h
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Thu, 26 Aug 2010 00:49:35 +0100
changeset 37 534b01198c2d
parent 0 7f656887cf89
permissions -rw-r--r--
Added ENotifyKeypresses and ECaptureCtrlC flags to CCommandBase. Commands can now get keypresses and handle ctrl-C via callbacks instead of having to implement custom active objects. As part of this extended the CCommandBase extension interface to MCommandExtensionsV2 for the new virtual functions KeyPressed(TUint aKeyCode, TUint aModifiers) and CtrlCPressed(). sudo now cleans up correctly by using ECaptureCtrlC.

// SensibleFormat.h
// 
// Copyright (c) 2006 - 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
// 
// Initial Contributors:
// Accenture - Initial contribution
//

// The purpose of this file is to define a generic format command that works reasonably even when there's no heap free
// Because it uses a stack buffer in this case, it is very difficult to make this a generic function without macroing

// Because I needed a 16-bit variant as well, and even templating would generate the same amount of code, I've done it
// as a #includable code snippet

// Note: If you do define SF_WIDE, Collapse() will be called on the result of the format before being passed to SF_ACTION

// If you want to pass in a VA_LIST, then #define SF_LIST aArgList
// If you want to pass in a bunch of arguments, #define SF_ARGLIST arg1,arg2,arg3

#if !defined(SF_FORMAT) || !defined(SF_BUF) || !defined(SF_ACTION)
#error "you must define all of SF_FORMAT, SF_BUF and SF_ACTION before including this file"
#endif

#if !((defined(SF_LIST) && !defined(SF_ARGLIST)) || (!defined(SF_LIST) && defined(SF_ARGLIST)))
#error "you must define exactly one of SF_LIST and SF_ARGLIST before including this file"
#endif

#ifndef COMMON_H
#error "you need to include common.h somewhere before including this file"
#endif

#ifdef SF_WIDE
#define TOverflowX TOverflow16
#define TBufX TBuf16<256>
#else
#define TOverflowX TOverflow8
#define TBufX TBuf8<256>
#endif

#ifdef SF_ARGLIST
#define SFAppend() AppendFormat(SF_FORMAT, &overflow, SF_ARGLIST)
#else
#define SFAppend() AppendFormatList(SF_FORMAT, SF_LIST, &overflow)
#endif

// Think of this as Format(RBuf8& SF_BUF, FunctionPointer SF_ACTION, const TDesCX& SF_FORMAT, TBool SF_STACKONLY, VA_LIST SF_LIST)
// where SF_ACTION(SF_BUF) is called passing in the fully formatted string
	{
	const TInt minBufSize = Max(SF_BUF.MaxSize(), 512);
	const TInt KMaxBufSize = 8192;
	TInt err = KErrNone;

#ifdef SF_STACKONLY
	if (SF_STACKONLY)
		{
		err = KErrNoMemory;
		}
	else
#endif
		{
		if (SF_BUF.MaxSize() == 0)
			{
			err = SF_BUF.Create(256);
			}
		else
			{
			SF_BUF.Zero();
			}
		}

	TOverflowX overflow;
	if (err == KErrNone)
		{
		// 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
		for (TInt bufSize = minBufSize; bufSize <= KMaxBufSize; bufSize*=2)
			{
			#ifdef SF_WIDE
				TPtr16 widePtr((TUint16*)SF_BUF.Ptr(), SF_BUF.MaxSize()/2);
				widePtr.SFAppend();
			#else
				SF_BUF.SFAppend();
			#endif
			if (!overflow.iOverflow)
				{
				// Then the format went ok
				#ifdef SF_WIDE
					TPtr8 collapsed = widePtr.Collapse();
					SF_ACTION(collapsed);
				#else
					SF_ACTION(SF_BUF);
				#endif
				break;
				}
			else
				{
				// Overflowed

				if (bufSize == KMaxBufSize)
					{
					// We've grown up to our (self-imposed) max buf size, so just live with the truncation
					#ifdef SF_WIDE
						TPtr8 collapsed = widePtr.Collapse();
						SF_ACTION(collapsed);
					#else
						SF_ACTION(SF_BUF);
					#endif
					break;
					}

				// Try and grow
				SF_BUF.Close();
				err = SF_BUF.Create(bufSize*2);
				if (err) break;
				else continue;
				}
			}
		}
	if (err)
		{
		// Last resort, use 256 char buf on the stack
		TBufX stackBuf;
		stackBuf.SFAppend(); // Silently truncate if overflow happens now
		#ifdef SF_WIDE
			TPtr8 collapsed = stackBuf.Collapse();
			SF_ACTION(collapsed);
		#else
			SF_ACTION(stackBuf);
		#endif
		}
	}

#undef SF_WIDE
#undef SF_FORMAT
#undef SF_LIST
#undef SF_ARGLIST
#undef SF_BUF
#undef SF_ACTION
#undef TBufX
#undef TOverflowX
#undef SFAppend
#undef SF_STACKONLY