コード例 #1
0
void VProfilingCounter::DumpStats()
{
	VString	string;
	string = GetCounterName();
	string += " : \r\n";
	string.AppendLong(fNbVal);
	string += " value\r\n";
	DebugMsg(string);
	
	string = "last value : ";
	string.AppendReal(GetDuration());
	string += "\r\n";
	DebugMsg(string);
	
	string = "min : ";
	string.AppendReal(fMin);
	string += "\r\n";
	DebugMsg(string);
	
	string = "max : ";
	string.AppendReal(fMax);
	string += "\r\n";
	DebugMsg(string);
	
	string = "average : ";
	string.AppendReal(fTotal/fNbVal);
	string += "\r\n";
	DebugMsg(string);
}
コード例 #2
0
void VSysLogOutput::Put( std::vector< const XBOX::VValueBag* >& inValuesVector)
{
	for (std::vector< const XBOX::VValueBag* >::iterator bagIter = inValuesVector.begin() ; bagIter != inValuesVector.end() ; ++bagIter)
	{
		EMessageLevel bagLevel = ILoggerBagKeys::level.Get( *bagIter);
		if ((fFilter & (1 << bagLevel)) != 0)
		{
			VString logMsg;
						
			VError errorCode = VE_OK;
			ILoggerBagKeys::error_code.Get( *bagIter, errorCode);
		
			VString loggerID;
			ILoggerBagKeys::source.Get( *bagIter, loggerID);
			
			OsType componentSignature = 0;
			if (!ILoggerBagKeys::component_signature.Get( *bagIter, componentSignature))
				componentSignature = COMPONENT_FROM_VERROR( errorCode);
			
			if (componentSignature != 0)
			{
				if (!loggerID.IsEmpty())
					loggerID.AppendUniChar( L'.');
				loggerID.AppendOsType( componentSignature);
			}
			
			if (!loggerID.IsEmpty())
				logMsg.Printf( "[%S]", &loggerID);
			
			// build message string
			VString message;
			
			if (errorCode != VE_OK)
				message.AppendPrintf( "error %d", ERRCODE_FROM_VERROR( errorCode));
			
			VString bagMsg;
			if (ILoggerBagKeys::message.Get( *bagIter, bagMsg))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( bagMsg);
			}
						
			sLONG taskId=-1;
			if (ILoggerBagKeys::task_id.Get( *bagIter, taskId))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"task #");
				message.AppendLong( taskId);
			}
			
			VString taskName;
			if (!ILoggerBagKeys::task_name.Get( *bagIter, taskName))
				VTask::GetCurrent()->GetName( taskName);
			if (!taskName.IsEmpty())
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( taskName);
			}
			
			sLONG socketDescriptor=-1;
			if (ILoggerBagKeys::socket.Get( *bagIter, socketDescriptor))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"socket ");
				message.AppendLong(socketDescriptor);
			}
			
			VString localAddr;
			if (ILoggerBagKeys::local_addr.Get( *bagIter, localAddr))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"local addr is ");
				message.AppendString( localAddr);
			}
			
			VString peerAddr;
			if (ILoggerBagKeys::peer_addr.Get( *bagIter, peerAddr))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"peer addr is ");
				message.AppendString( peerAddr);
			}
			
			bool exchangeEndPointID=false;
			if (ILoggerBagKeys::exchange_id.Get( *bagIter, exchangeEndPointID))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( (exchangeEndPointID) ? L"exchange endpoint id" : L"do not exchange endpoint id");
			}
			
			bool isBlocking=false;
			if (ILoggerBagKeys::is_blocking.Get( *bagIter, isBlocking))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( (isBlocking) ? L"is blocking" : L"is not blocking");
			}
			
			bool isSSL=false;
			if (ILoggerBagKeys::is_ssl.Get( *bagIter, isSSL))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( (isSSL) ? L"with SSL" : L"without SSL");
			}
			
			bool isSelectIO=false;
			if (ILoggerBagKeys::is_select_io.Get( *bagIter, isSelectIO))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( (isSelectIO) ? L"with SelectIO" : L"without SelectIO");
			}
			
			sLONG ioTimeout=-1;
			if (ILoggerBagKeys::ms_timeout.Get( *bagIter, ioTimeout))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"with ");
				message.AppendLong( ioTimeout);
				message.AppendString( L"ms timeout");
			}
			
			sLONG askedCount=-1;
			if (ILoggerBagKeys::count_bytes_asked.Get( *bagIter, askedCount))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"asked for ");
				message.AppendLong( askedCount);
				message.AppendString( L" byte(s)");
			}
			
			sLONG sentCount=-1;
			if (ILoggerBagKeys::count_bytes_sent.Get(*bagIter, sentCount))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"sent ");
				message.AppendLong( sentCount);
				message.AppendString( L" byte(s)");
			}
			
			sLONG receivedCount=-1;
			if (ILoggerBagKeys::count_bytes_received.Get( *bagIter, receivedCount))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"received ");
				message.AppendLong( receivedCount);
				message.AppendString( L" byte(s)");
			}
			
			sLONG ioSpent=-1;
			if (ILoggerBagKeys::ms_spent.Get( *bagIter, ioSpent))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"done in ");
				message.AppendLong( ioSpent);
				message.AppendString( L"ms");
			}
			
			sLONG dumpOffset=-1;
			if (ILoggerBagKeys::dump_offset.Get( *bagIter, dumpOffset))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"offset ");
				message.AppendLong( dumpOffset);
			}
			
			VString dumpBuffer;
			if (ILoggerBagKeys::dump_buffer.Get( *bagIter, dumpBuffer))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L"data : ");
				message.AppendString( dumpBuffer);
			}
			
			VString fileName;
			if (ILoggerBagKeys::file_name.Get( *bagIter, fileName))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( fileName);
			}
			
			sLONG lineNumber;
			if (ILoggerBagKeys::line_number.Get( *bagIter, lineNumber))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendLong( lineNumber);
			}
			
			VString stackCrawl;
			if (ILoggerBagKeys::stack_crawl.Get( *bagIter, stackCrawl))
			{
				if (!message.IsEmpty())
					message.AppendString( L", ");
				message.AppendString( L", {");
				stackCrawl.ExchangeAll( L"\n", L" ; ");
				message.AppendString( stackCrawl);
				message.AppendUniChar( L'}');
			}
			
			if (!logMsg.IsEmpty())
				logMsg.AppendUniChar( L' ');
			logMsg.AppendString( message);
			
			if (!logMsg.IsEmpty())
			{
				StStringConverter<char> messageConverter( VTC_StdLib_char);
		
				switch( bagLevel)
				{
					case EML_Dump:
					case EML_Assert:
					case EML_Debug:
						syslog( LOG_DEBUG, messageConverter.ConvertString( logMsg));
						break;
						
					case EML_Trace:
						syslog( LOG_NOTICE, messageConverter.ConvertString( logMsg));
						break;

					case EML_Information:
						syslog( LOG_INFO, messageConverter.ConvertString( logMsg));
						break;
							   
					case EML_Warning:
						syslog( LOG_WARNING, messageConverter.ConvertString( logMsg));
						break;
							   
					case EML_Error:
						syslog( LOG_ERR, messageConverter.ConvertString( logMsg));
						break;
						
					case EML_Fatal:
						syslog( LOG_CRIT, messageConverter.ConvertString( logMsg));
						break;
							   
				   default:
					   assert(false);
					   break;
				}
			}
		}
	}
}
コード例 #3
0
static void _ExplainTTRFormat_V1()
{
	VString		doc;

	char		theTime[512] = {0};
	time_t now = ::time( NULL);
	::strftime( theTime, sizeof( theTime),"%Y-%m-%dT%H:%M:%S", localtime( &now));

	doc = "Text (Tab-Tab-Return) format version ";
	doc.AppendLong(kTTR_FORMAT_VERSION);
	doc.AppendCString("\r\r");

	// ===============================================
	doc += "--------------------------------------------------\r";
	doc += "General\r";
	doc += "--------------------------------------------------\r";
	doc.AppendPrintf("Every entry is quoted by square brackets. For example: [%d] for \"FlushFromLanguage\".\r", eCLEntryKind_FlushFromLanguage);
	doc.AppendPrintf("First entry in the log is the \"start\" entry (%d), it gives the current date-time.\r", eCLEntryKind_Start);
	doc += "Then, every other entry is followed by [tab] ellapsed second since log started [tab] Task ID {and optionnaly: [tab] other infos...}\r\r";
	doc += "For example, when the log starts, first line is something like:\r";
	doc.AppendPrintf("[%d]\t%s\t10\r", eCLEntryKind_Start, theTime);
	doc += "Then you may have (FlushFromLanguage, executed 5 seconds since the log started, for task ID 10):\r";
	doc.AppendPrintf("[%d]\t5\t10\r", eCLEntryKind_FlushFromLanguage);

	doc += "\rEntries may be quoted with start/end. In this case, the format is [entry num]s and [entry num]e.";
	doc += " Between both tags, several other entries may be logged, from the same task ID or from others.\r";
	doc += "In all cases, the 'end' tag is formatted: [entry num]e [tab] ellapsed second since log started [tab] taskID [tab] count of milliseconds since [entry num]start\r";
	doc += "For example, with the FlushFromLanguage kind launched from task ID 10, the log could be:\r";
	doc.AppendPrintf("[%d]s\t123\t10\t(...other infos - see format)\r", eCLEntryKind_FlushFromLanguage);
	doc += ". . .\r. . .\r. . .\r";
	doc.AppendPrintf("[%d]s\t126\t10\t(...other infos - see format)\r", eCLEntryKind_FlushFromLanguage);

	// ===============================================
	doc += "--------------------------------------------------\r";
	doc += "List of all kinds of entry (name [tab] value)\r";
	doc += "--------------------------------------------------\r";
	doc.AppendPrintf("Unknown\t%d\r", eCLEntryKind_Unknown);
	doc.AppendPrintf("Start\t%d\r", eCLEntryKind_Start);
	doc.AppendPrintf("Stop\t%d\r", eCLEntryKind_Stop);
	doc.AppendPrintf("Comment\t%d\r", eCLEntryKind_Comment);
	doc.AppendPrintf("NeedsBytes\t%d\r", eCLEntryKind_NeedsBytes);
	doc.AppendPrintf("CallNeedsBytes\t%d\r", eCLEntryKind_CallNeedsBytes);
	doc.AppendPrintf("FlushFromLanguage\t%d\r", eCLEntryKind_FlushFromLanguage);
	doc.AppendPrintf("FlushFromMenuCommand\t%d\r", eCLEntryKind_FlushFromMenuCommand);
	doc.AppendPrintf("FlushFromScheduler\t%d\r", eCLEntryKind_FlushFromScheduler);
	doc.AppendPrintf("FlushFromBackup\t%d\r", eCLEntryKind_FlushFromBackup);
	doc.AppendPrintf("FlushFromNeedsBytes\t%d\r", eCLEntryKind_FlushFromNeedsBytes);
	doc.AppendPrintf("FlushFromRemote\t%d\r", eCLEntryKind_FlushFromRemote);
	doc.AppendPrintf("FlushFromUnknown\t%d\r", eCLEntryKind_FlushFromUnknown);
	doc.AppendPrintf("Flush\t%d\r", eCLEntryKind_Flush);
	doc.AppendPrintf("MemStats\t%d\r", eCLEntryKind_MemStats);

	doc.AppendCString("\r\r");

	// ===============================================
	doc += "--------------------------------------------------\r";
	doc += "Format and meaning of each kind\r";
	doc += "--------------------------------------------------\r";

	doc.AppendPrintf("[%d]\r", eCLEntryKind_Unknown);
	doc += "Unknown entry kind\r";
	doc.AppendPrintf("[%d] [tab] ellapsed second since log started [tab] taskID\r\r", eCLEntryKind_Unknown);

	doc.AppendPrintf("[%d]\r", eCLEntryKind_Start);
	doc += "The log starts. Quoted (start/end) entry, with misc. infos between the start and the end.\r";
	doc.AppendPrintf("[%d]s [tab] current time [tab] taskID [tab] version [cr]\r", eCLEntryKind_Start);
	doc.AppendPrintf("struct [tab] path to host database structure file [cr]\r");
	doc.AppendPrintf("data [tab] path to host database data file [cr]\r");
	doc.AppendPrintf("[%d]e\r\r", eCLEntryKind_Start);

	doc.AppendPrintf("[%d]\r", eCLEntryKind_Stop);
	doc += "The log ends\r";
	doc.AppendPrintf("[%d] [tab] ellapsed second since log started [tab] taskID\r\r", eCLEntryKind_Stop);

	doc.AppendPrintf("[%d]\r", eCLEntryKind_Comment);
	doc += "A comment added by the developer. Comments are always quoted with start and end, a \\r is added at beginning and end.\r";
	doc.AppendPrintf("[%d]start [tab] ellapsed second since log started [tab] taskID [cr] the comment [cr] [%d]end [tab] time [tab] taskID [tab] 0 (the milliseconds)\r\r", eCLEntryKind_Comment);

	doc.AppendPrintf("[%d]\r", eCLEntryKind_NeedsBytes);
	doc += "Any source asks memory to the cache manager\r";
	doc.AppendPrintf("[%d] [tab] ellapsed second since log started [tab] taskID [tab] task name [tab] process 4D num [tab] needed bytes (very large int.)\r", eCLEntryKind_NeedsBytes);
	doc.AppendPrintf("Note: may be followed by [%d]\r\r", eCLEntryKind_MemStats);

	doc.AppendPrintf("[%d]\r", eCLEntryKind_CallNeedsBytes);
	doc += "Memory manager asks memory to the cache manager: not enough space in the cache to allocate memory. The cache manager will try to free unused objects, to flush, etc...\r";
	doc.AppendPrintf("[%d] [tab] ellapsed second since log started [tab] taskID [tab] task name [tab] process 4D num [tab] needed bytes (very large int.)\r", eCLEntryKind_CallNeedsBytes);
	doc.AppendPrintf("Note: may be followed by [%d]\r\r", eCLEntryKind_MemStats);

	doc.AppendPrintf("[%d], [%d], [%d], [%d], [%d], [%d], [%d]\r", eCLEntryKind_FlushFromLanguage,
																	eCLEntryKind_FlushFromMenuCommand,
																	eCLEntryKind_FlushFromScheduler,
																	eCLEntryKind_FlushFromBackup,
																	eCLEntryKind_FlushFromNeedsBytes,
																	eCLEntryKind_FlushFromRemote,
																	eCLEntryKind_FlushFromUnknown);
	doc += "Action at the origin of a flush. All the 'FlushFrom...' share the same format.\r";
	doc.AppendPrintf("[%d] [tab] ellapsed second since log started [tab] taskID [tab] task name [tab] process 4D num [tab] isWaitUntilDone (1 = yes, 0 = no, -1 = unknown) [tab] isEmptyCache (1 = yes, 0 = no, -1 = unknown)\r", eCLEntryKind_CallNeedsBytes);
	doc.AppendPrintf("Note: may be followed by [%d]\r", eCLEntryKind_MemStats);
	doc.AppendPrintf("Note: [%d] means a flush was requested from the remote, but we don't have the exact origin (does a client called FLUSH BUFFERS explicitely? ...)\r\r", eCLEntryKind_FlushFromRemote);

	doc.AppendPrintf("[%d]\r", eCLEntryKind_Flush);
	doc += "Flush (we are inside the Flush Manager)\r";
	doc.AppendPrintf("[%d] [tab] ellapsed second since log started [tab] taskID\r", eCLEntryKind_Flush);
	doc.AppendPrintf("Note: may be followed by [%d]\r\r", eCLEntryKind_MemStats);

	doc.AppendPrintf("[%d]\r", eCLEntryKind_MemStats);
	doc += "The memory statistics. Level of stats is a bit field, to get specific stats, add the following values:\r";
	doc.AppendPrintf("Mini stats (default value): %d\r", eCLDumpStats_Mini);
	doc.AppendPrintf("Objects: %d\r", eCLDumpStats_Objects);
	doc.AppendPrintf("Blocks: %d\r", eCLDumpStats_Blocks);
	doc.AppendPrintf("SmallBlocks: %d\r", eCLDumpStats_SmallBlocks);
	doc.AppendPrintf("BigBlocks: %d\r", eCLDumpStats_BigBlocks);
	doc.AppendPrintf("OtherBlocks: %d\r", eCLDumpStats_OtherBlocks);
	doc.AppendPrintf("All: %d\r", eCLDumpStats_All);

	doc.AppendPrintf("[%d] [tab] ellapsed second since log started [tab] taskID [tab] origin of the stats (a log entry number) [cr] the stats\r", eCLEntryKind_MemStats);
	doc += "the stats themselves are in xml:\r";
	doc += "Main tag: <mem_stats level=\"stat level\" size=\"total amount of memory\" used=\"amount ofused memory\">\r";
	doc += "Then come the details:\r";
	doc += "<system phys=\"physical memory size\" free=\"free memory size\" app_used_phys=\"physical used by app\" used_virtual=\"virtual meory used\" />\r";
	doc += "Allocations blocks: <alloc count=\"number of virtual allocations\" tot=\"total allocated\" />\r";
	doc += "Then come the detailed stats, depending on the level. Note: infos are the same as the one found in GET CACHE STATISTIC.";
	doc += ", the xml uses some abbreviations to reduce a bit the size: bb = \"big blocks\", sb = \"small blocks\", ob = \"other blocks\"\r";
	doc += "Example of log:\r";

	doc += "<mem_stats level=\"1\" tid=\"13\" tname=\"P_1\" pnum=\"5\" size=\"10704570434977792\" used=\"2306663092733982407\">\r";
	doc += "<system phys=\"2143993856\" free=\"1\" app_used_phys=\"2882306048\" used_virtual=\"0\"/>";
	doc += "<alloc count=\"2\" tot=\"104857600\"/>";
	doc += "<stats free=\"102365184\" nb_bb=\"165\" used_bb=\"163\" free_bb=\"2\" nb_pages=\"104\" nb_sb=\"4411\" used_sb=\"4401\" free_sb=\"10\" biggest_block=\"70124512\" biggest_free_block=\"70124512\" nb_obj=\"3852\"/>";
	doc += "</mem_stats>\r\r";

	VFolder *userDocsFolder = VFolder::RetainSystemFolder(eFK_UserDocuments, false);
	if(userDocsFolder != NULL)
	{
		VFile	logDoc(*userDocsFolder, CVSTR("cache_log_doc_v1.txt"));

		VError err = VE_OK;
		if(logDoc.Exists())
			err = logDoc.Delete();

		err = logDoc.Create();

		if(err == VE_OK)
		{
			VFileStream logDocDump(&logDoc);

			err = logDocDump.OpenWriting();

			if(err == VE_OK)
			{
				logDocDump.PutText(doc);
			}
			
			
			if(err == VE_OK)
				err = logDocDump.CloseWriting();
		}
		userDocsFolder->Release();
	}

}
コード例 #4
0
void XWinIntlMgr::FormatDate( const VTime& inDate, VString& outDate, EOSFormats inFormat, bool inUseGMTTimeZoneForDisplay)
{
	// Prepare SYSTEMTIME for windows.
	sWORD YY = 0;
	sWORD MM = 0;
	sWORD DD = 0;
	sWORD hh = 0;
	sWORD mm = 0;
	sWORD ss = 0;
	sWORD ms = 0;
	if (inUseGMTTimeZoneForDisplay)
		inDate.GetUTCTime (YY,MM,DD,hh,mm,ss,ms);
	else
		inDate.GetLocalTime (YY,MM,DD,hh,mm,ss,ms);

	// Verify if date >1st Jan 1601 (GetDateFormat doesn't support earlier dates.
	if (YY>=1601)
	{
		// Let the OS do it's job.
		UniChar acBuffer[256];

		SYSTEMTIME osDate={0};
		osDate.wYear=YY;
		osDate.wMonth=MM;
		osDate.wDay=DD;
		osDate.wHour=hh;
		osDate.wMinute=mm;
		osDate.wSecond=ss;
		osDate.wMilliseconds=ms;

		if (inFormat == eOS_MEDIUM_FORMAT)
		{
			VString pattern;
			if (GetLocaleInfo( LOCALE_SLONGDATE, pattern))
			{
				// replace long month and date by medium ones
				pattern.ExchangeRawString( CVSTR( "MMMM"), CVSTR( "MMM"));
				pattern.ExchangeRawString( CVSTR( "dddd"), CVSTR( "ddd"));
				if (::GetDateFormatW( fDialect, 0, &osDate, pattern.GetCPointer(), acBuffer, sizeof(acBuffer)))
					outDate = acBuffer;
			}
		}
		else
		{
			// Let the OS do the stuff.
			DWORD dateFormat = (inFormat == eOS_SHORT_FORMAT) ? DATE_SHORTDATE : DATE_LONGDATE;
			if (::GetDateFormatW(fDialect,dateFormat,&osDate,NULL,acBuffer,sizeof(acBuffer)))
				outDate = acBuffer;
		}
	}
	else
	{
		// Get the date pattern
		VString pattern;
		if (GetLocaleInfo( (inFormat == eOS_LONG_FORMAT) ? LOCALE_SLONGDATE : LOCALE_SSHORTDATE, pattern))
		{
			XBOX::VString tokens="gyMd";
			UniChar oldToken=0;
			sLONG count=0;
			pattern.AppendChar(' ');
			sLONG YY2=YY%100;
			XBOX::VString oneName;
			for (int pos=0;pos<pattern.GetLength();pos++)
			{
				UniChar token=pattern[pos];
				if (tokens.FindUniChar(token)>=1)
				{
					if (token==oldToken)
						count++;
					else
					{
						if (!count)
						{
							count=1;
							oldToken=token;
						}
					}
				}

				if (count && token!=oldToken)
				{
					switch(oldToken)
					{
					case 'g':
						if (count==2)
						{
							// TODO: ERA will be added if really wanted.
						}
						else
						{
							for (int i=0;i<count;i++)
								outDate.AppendUniChar(oldToken);
						}
						break;

					case 'y':	// YEAR
						switch(count)
						{
						case 5:
						case 4:		// 4 or more digits date
							outDate.AppendLong(YY);
							break;

						case 2:		// 2 digits with starting 0.
							if (YY2<=9)
								outDate.AppendLong(0);
						case 1:		// 1 or 2 digits
							outDate.AppendLong(YY2);
							break;

						default:
							for (int i=0;i<count;i++)
								outDate.AppendUniChar(oldToken);
							break;
						}
						break;

					case 'M':	// MONTH
						switch(count)
						{
						case 4:	// Long name
						case 3:	// Abbreviated name
							if (GetLocaleInfo( ((count==4) ? LOCALE_SMONTHNAME1 : LOCALE_SABBREVMONTHNAME1) + MM - 1, oneName))
								outDate += oneName;
							break;

						case 2:	// 2 digits number (leading 0)
							if (MM<=9)
								outDate.AppendLong(0);
						case 1:	// 1 or 2 digits number
							outDate.AppendLong(MM);
							break;

						default:
							for (int i=0;i<count;i++)
								outDate.AppendUniChar(oldToken);
							break;
						}
						break;

					case 'd':	// DAY
						switch(count)
						{
						case 4:	// Weekday long name
						case 3:	// Weekday abbreviated name
							if (GetLocaleInfo( ((count==4) ? LOCALE_SDAYNAME1 : LOCALE_SABBREVDAYNAME1) + (inDate.GetWeekDay() + 6) % 7, oneName))
								outDate += oneName;
							break;

						case 2:	// Month day on 2 digits (leading 0)
							if (DD<=9)
								outDate.AppendLong(0);
						case 1:	// Month day on 1 or 2 digits.
							outDate.AppendLong(DD);
							break;

						default:
							for (int i=0;i<count;i++)
								outDate.AppendUniChar(oldToken);
							break;
						}
						break;

					}
					count=0;
				}

				if (!count)
					outDate.AppendUniChar(token);
				oldToken=token;
			}

			// Remove the extra space at end of pattern.
			if (outDate.GetLength()>1)
				outDate.SubString(1,outDate.GetLength()-1);
		}
	}
}