libraries/clogger/inc/SensibleFormat.h
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libraries/clogger/inc/SensibleFormat.h	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,145 @@
+// 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