First submission to Symbian Foundation staging server.
// 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