|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <memspy/engine/memspyengineoutputsink.h> |
|
19 |
|
20 // User includes |
|
21 #include <memspy/engine/memspyengineutils.h> |
|
22 |
|
23 // Constants |
|
24 const TInt KMemSpyItemAndValueAlignmentAmount = 30; |
|
25 const TInt KMemSpyNumericFormatBufferSize = 20; |
|
26 |
|
27 // Literal constants |
|
28 _LIT( KMemSpyNumericHexFormat, "0x%08x" ); |
|
29 _LIT( KMemSpyNumericDecFormat, "%d" ); |
|
30 _LIT( KMemSpyDataStreamFolderNameFormatSpec, "%04d%02d%02d - %02dh %02dm %02ds" ); |
|
31 |
|
32 |
|
33 CMemSpyEngineOutputSink::CMemSpyEngineOutputSink( CMemSpyEngine& aEngine ) |
|
34 : iEngine( aEngine ), iFormatBufferPointer( NULL, 0 ) |
|
35 { |
|
36 } |
|
37 |
|
38 |
|
39 CMemSpyEngineOutputSink::~CMemSpyEngineOutputSink() |
|
40 { |
|
41 delete iFormatBuffer; |
|
42 delete iPrefix; |
|
43 delete iLocalBuffer; |
|
44 delete iDataStreamTimeStampSpecifier; |
|
45 } |
|
46 |
|
47 |
|
48 void CMemSpyEngineOutputSink::BaseConstructL() |
|
49 { |
|
50 iFormatBuffer = HBufC::NewL( 1024 ); |
|
51 iFormatBufferPointer.Set( iFormatBuffer->Des() ); |
|
52 iPrefix = HBufC::NewL( 2048 ); |
|
53 iLocalBuffer = HBufC::NewL( 2048 ); |
|
54 } |
|
55 |
|
56 |
|
57 EXPORT_C void CMemSpyEngineOutputSink::DataStreamTimeStampBeginL( const TTime& aTime ) |
|
58 { |
|
59 const TDateTime dt( aTime.DateTime() ); |
|
60 |
|
61 // Build it up... |
|
62 HBufC* spec = HBufC::NewL( KMaxFileName ); |
|
63 TPtr pName( spec->Des() ); |
|
64 pName.Format( KMemSpyDataStreamFolderNameFormatSpec, dt.Year(), dt.Month()+1, dt.Day()+1, dt.Hour(), dt.Minute(), dt.Second()); |
|
65 |
|
66 DataStreamTimeStampEnd(); |
|
67 iDataStreamTimeStampSpecifier = spec; |
|
68 } |
|
69 |
|
70 |
|
71 EXPORT_C void CMemSpyEngineOutputSink::DataStreamTimeStampEnd() |
|
72 { |
|
73 delete iDataStreamTimeStampSpecifier; |
|
74 iDataStreamTimeStampSpecifier = NULL; |
|
75 } |
|
76 |
|
77 |
|
78 EXPORT_C void CMemSpyEngineOutputSink::DataStreamBeginL( const TDesC& aContext ) |
|
79 { |
|
80 DataStreamBeginL( aContext, KNullDesC ); |
|
81 } |
|
82 |
|
83 |
|
84 EXPORT_C void CMemSpyEngineOutputSink::DataStreamBeginL( const TDesC& aContext, const TDesC& aFolder ) |
|
85 { |
|
86 DataStreamBeginL( aContext, aFolder, KNullDesC ); |
|
87 } |
|
88 |
|
89 |
|
90 void CMemSpyEngineOutputSink::ProcessSuspendedL( TProcessId /*aId*/ ) |
|
91 { |
|
92 } |
|
93 |
|
94 |
|
95 void CMemSpyEngineOutputSink::ProcessResumed( TProcessId /*aId*/ ) |
|
96 { |
|
97 } |
|
98 |
|
99 |
|
100 TBool CMemSpyEngineOutputSink::IsPrefixAllowed( const TDesC& /*aPrefix*/ ) |
|
101 { |
|
102 return ETrue; |
|
103 } |
|
104 |
|
105 |
|
106 EXPORT_C void CMemSpyEngineOutputSink::OutputPrefixSetLC( const TDesC& aPrefix ) |
|
107 { |
|
108 __ASSERT_ALWAYS( aPrefix.Length() <= iPrefix->Des().MaxLength(), User::Invariant() ); |
|
109 TPtr pPrefix( iPrefix->Des() ); |
|
110 pPrefix.Zero(); |
|
111 |
|
112 if ( IsPrefixAllowed( aPrefix ) ) |
|
113 { |
|
114 pPrefix.Copy( aPrefix ); |
|
115 } |
|
116 |
|
117 CleanupStack::PushL( TCleanupItem( ClearPrefix, this ) ); |
|
118 } |
|
119 |
|
120 |
|
121 EXPORT_C void CMemSpyEngineOutputSink::OutputPrefixSetFormattedLC( TRefByValue<const TDesC> aFormat, ... ) |
|
122 { |
|
123 VA_LIST list; |
|
124 VA_START(list,aFormat); |
|
125 // |
|
126 iFormatBufferPointer.Zero(); |
|
127 iFormatBufferPointer.FormatList( aFormat, list ); |
|
128 // |
|
129 OutputPrefixSetLC( iFormatBufferPointer ); |
|
130 } |
|
131 |
|
132 |
|
133 EXPORT_C void CMemSpyEngineOutputSink::OutputPrefixClear() |
|
134 { |
|
135 iPrefix->Des().Zero(); |
|
136 } |
|
137 |
|
138 |
|
139 EXPORT_C void CMemSpyEngineOutputSink::OutputRawL( const TDesC8& aData ) |
|
140 { |
|
141 DoOutputRawL( aData ); |
|
142 } |
|
143 |
|
144 |
|
145 EXPORT_C void CMemSpyEngineOutputSink::OutputLineL( const TDesC& aLine, TBool aIncludePrefix ) |
|
146 { |
|
147 TPtr pBuffer( iLocalBuffer->Des() ); |
|
148 if ( aIncludePrefix ) |
|
149 { |
|
150 pBuffer.Copy( *iPrefix ); |
|
151 } |
|
152 else |
|
153 { |
|
154 pBuffer.Zero(); |
|
155 } |
|
156 |
|
157 pBuffer.Append( aLine ); |
|
158 DoOutputLineL( pBuffer ); |
|
159 } |
|
160 |
|
161 |
|
162 EXPORT_C void CMemSpyEngineOutputSink::OutputLineFormattedL( TRefByValue<const TDesC> aFormat, ... ) |
|
163 { |
|
164 VA_LIST list; |
|
165 VA_START(list,aFormat); |
|
166 |
|
167 iFormatBufferPointer.Zero(); |
|
168 iFormatBufferPointer.FormatList( aFormat, list ); |
|
169 // |
|
170 OutputLineL( iFormatBufferPointer ); |
|
171 } |
|
172 |
|
173 |
|
174 EXPORT_C void CMemSpyEngineOutputSink::OutputBlankLineL() |
|
175 { |
|
176 DoOutputLineL( KNullDesC ); |
|
177 } |
|
178 |
|
179 |
|
180 EXPORT_C void CMemSpyEngineOutputSink::OutputSectionHeadingL( const TDesC& aCaption, TChar aUnderlineCharacter ) |
|
181 { |
|
182 OutputBlankLineL(); |
|
183 OutputLineL( aCaption ); |
|
184 // |
|
185 HBufC* underline = HBufC::NewLC( aCaption.Length() ); |
|
186 TPtr pUnderline( underline->Des() ); |
|
187 pUnderline.Fill( aUnderlineCharacter, aCaption.Length()); |
|
188 OutputLineL( *underline ); |
|
189 CleanupStack::PopAndDestroy( underline ); |
|
190 } |
|
191 |
|
192 |
|
193 EXPORT_C void CMemSpyEngineOutputSink::OutputItemAndValueL( const TDesC& aItem, const TDesC& aValue ) |
|
194 { |
|
195 FormatBuffer().Zero(); |
|
196 FormatBuffer().Append( aItem ); |
|
197 FormatBuffer().Append( ':' ); |
|
198 |
|
199 const TInt padAmount = KMemSpyItemAndValueAlignmentAmount - aItem.Length(); |
|
200 |
|
201 FormatBuffer().AppendFill(' ', padAmount); |
|
202 FormatBuffer().Append( ' ' ); |
|
203 FormatBuffer().Append( aValue ); |
|
204 |
|
205 OutputLineL( FormatBuffer() ); |
|
206 } |
|
207 |
|
208 |
|
209 EXPORT_C void CMemSpyEngineOutputSink::OutputItemAndValueL( const TDesC& aItem, TUint aValue, TBool aHex ) |
|
210 { |
|
211 TBuf<KMemSpyNumericFormatBufferSize> val; |
|
212 // |
|
213 if ( aHex ) |
|
214 { |
|
215 val.Format( KMemSpyNumericHexFormat, aValue ); |
|
216 } |
|
217 else |
|
218 { |
|
219 val.Format( KMemSpyNumericDecFormat, aValue ); |
|
220 } |
|
221 // |
|
222 OutputItemAndValueL( aItem, val ); |
|
223 } |
|
224 |
|
225 |
|
226 EXPORT_C void CMemSpyEngineOutputSink::OutputBinaryDataL( const TDesC& aFormat, const TUint8* aBufferAddress, const TUint8* aDisplayStartAddress, TInt aLength ) |
|
227 { |
|
228 _LIT(KAddresPostfix, ": "); |
|
229 _LIT(KDoubleSpace, " "); |
|
230 _LIT(KSingleSpace, " "); |
|
231 |
|
232 const TInt maxLen = aLength; |
|
233 TInt len = aLength; |
|
234 const TUint8* pDataAddr = aBufferAddress; |
|
235 |
|
236 TBuf<81> out; |
|
237 TBuf<20> ascii; |
|
238 TInt offset = 0; |
|
239 const TUint8* a = pDataAddr; |
|
240 const TUint8* displayAddress = aDisplayStartAddress; |
|
241 // |
|
242 while(len>0) |
|
243 { |
|
244 out.Zero(); |
|
245 ascii.Zero(); |
|
246 out.AppendNumFixedWidth((TUint) displayAddress, EHex, 8); |
|
247 out.Append(KAddresPostfix); |
|
248 |
|
249 TUint b; |
|
250 for (b=0; b<16; b++) |
|
251 { |
|
252 TUint8 c = ' '; |
|
253 if ((pDataAddr + offset + b) < pDataAddr + maxLen) |
|
254 { |
|
255 c = *(pDataAddr + offset + b); |
|
256 out.AppendNumFixedWidth(c, EHex, 2); |
|
257 } |
|
258 else |
|
259 { |
|
260 out.Append(KDoubleSpace); |
|
261 } |
|
262 out.Append( KSingleSpace ); |
|
263 if (c<=0x20 || c == 0x27 || c>=0x7f || c=='%') |
|
264 c=0x2e; |
|
265 ascii.Append(TChar(c)); |
|
266 } |
|
267 out.Append(ascii); |
|
268 out.ZeroTerminate(); |
|
269 |
|
270 FormatBuffer().Format( aFormat, &out ); |
|
271 OutputLineL( FormatBuffer() ); |
|
272 |
|
273 displayAddress += 16; |
|
274 a += 16; |
|
275 offset += 16; |
|
276 len -= 16; |
|
277 } |
|
278 } |
|
279 |
|
280 |
|
281 EXPORT_C void CMemSpyEngineOutputSink::OutputBinaryDataCompressedL( const TDesC& aFormat, const TUint8* aBufferAddress, const TUint8* aDisplayStartAddress, TInt aLength ) |
|
282 { |
|
283 _LIT(KAddresPostfix, ": "); |
|
284 _LIT(KDoubleSpace, " "); |
|
285 |
|
286 const TInt maxLen = aLength; |
|
287 TInt len = aLength; |
|
288 const TUint8* pDataAddr = aBufferAddress; |
|
289 |
|
290 TBuf<81> out; |
|
291 TInt offset = 0; |
|
292 const TUint8* a = pDataAddr; |
|
293 const TUint8* displayAddress = aDisplayStartAddress; |
|
294 // |
|
295 while(len>0) |
|
296 { |
|
297 out.Zero(); |
|
298 out.AppendNumFixedWidth((TUint) displayAddress, EHex, 8); |
|
299 out.Append(KAddresPostfix); |
|
300 |
|
301 TUint b; |
|
302 for (b=0; b<16; b++) |
|
303 { |
|
304 TUint8 c = ' '; |
|
305 if ((pDataAddr + offset + b) < pDataAddr + maxLen) |
|
306 { |
|
307 c = *(pDataAddr + offset + b); |
|
308 out.AppendNumFixedWidth(c, EHex, 2); |
|
309 } |
|
310 else |
|
311 { |
|
312 out.Append(KDoubleSpace); |
|
313 } |
|
314 if (c<=0x20 || c>=0x7f || c=='%') |
|
315 c=0x2e; |
|
316 } |
|
317 out.ZeroTerminate(); |
|
318 |
|
319 FormatBuffer().Format( aFormat, &out ); |
|
320 OutputLineL( FormatBuffer() ); |
|
321 |
|
322 displayAddress += 16; |
|
323 a += 16; |
|
324 offset += 16; |
|
325 len -= 16; |
|
326 } |
|
327 } |
|
328 |
|
329 |
|
330 TPtr& CMemSpyEngineOutputSink::FormatBuffer() |
|
331 { |
|
332 return iFormatBufferPointer; |
|
333 } |
|
334 |
|
335 |
|
336 CMemSpyEngine& CMemSpyEngineOutputSink::Engine() |
|
337 { |
|
338 return iEngine; |
|
339 } |
|
340 |
|
341 |
|
342 void CMemSpyEngineOutputSink::ClearPrefix( TAny* aSelf ) |
|
343 { |
|
344 CMemSpyEngineOutputSink* self = reinterpret_cast< CMemSpyEngineOutputSink* >( aSelf ); |
|
345 self->OutputPrefixClear(); |
|
346 } |
|
347 |
|
348 |
|
349 const TDesC& CMemSpyEngineOutputSink::DataStreamTimeStamp() const |
|
350 { |
|
351 if ( iDataStreamTimeStampSpecifier ) |
|
352 { |
|
353 return *iDataStreamTimeStampSpecifier; |
|
354 } |
|
355 |
|
356 return KNullDesC; |
|
357 } |
|
358 |
|
359 |
|
360 |
|
361 |
|
362 |
|
363 |
|
364 |
|
365 |
|
366 |
|
367 |
|
368 |
|
369 |
|
370 |
|
371 |
|
372 |
|
373 |
|
374 |
|
375 CMemSpyEngineSinkMetaData::CMemSpyEngineSinkMetaData( TBool aOverwrite, TBool aUseFileTimeStamp ) |
|
376 : iOverwrite( aOverwrite ), iUseFileTimeStamp( aUseFileTimeStamp ) |
|
377 { |
|
378 } |
|
379 |
|
380 |
|
381 EXPORT_C CMemSpyEngineSinkMetaData::~CMemSpyEngineSinkMetaData() |
|
382 { |
|
383 delete iContext; |
|
384 delete iFolder; |
|
385 delete iExtension; |
|
386 delete iFolderTimeStamp; |
|
387 } |
|
388 |
|
389 |
|
390 void CMemSpyEngineSinkMetaData::ConstructL( const TDesC& aContext, const TDesC& aFolder, const TDesC& aExtension, const TTime& aFolderTime ) |
|
391 { |
|
392 iContext = aContext.AllocL(); |
|
393 iFolder = aFolder.AllocL(); |
|
394 iExtension = aExtension.AllocL(); |
|
395 |
|
396 const TDateTime dt = aFolderTime.DateTime(); |
|
397 HBufC* spec = HBufC::NewLC( KMaxFileName ); |
|
398 TPtr pName( spec->Des() ); |
|
399 pName.Format( KMemSpyDataStreamFolderNameFormatSpec, dt.Year(), dt.Month()+1, dt.Day()+1, dt.Hour(), dt.Minute(), dt.Second()); |
|
400 iFolderTimeStamp = pName.AllocL(); |
|
401 CleanupStack::PopAndDestroy( spec ); |
|
402 } |
|
403 |
|
404 |
|
405 EXPORT_C CMemSpyEngineSinkMetaData* CMemSpyEngineSinkMetaData::NewL() |
|
406 { |
|
407 return CMemSpyEngineSinkMetaData::NewL( KNullDesC, KNullDesC, KNullDesC, ETrue, ETrue ); |
|
408 } |
|
409 |
|
410 |
|
411 EXPORT_C CMemSpyEngineSinkMetaData* CMemSpyEngineSinkMetaData::NewL( const TDesC& aContext, const TDesC& aFolder, const TDesC& aExtension, TBool aOverwrite, TBool aUseFileTimeStamp ) |
|
412 { |
|
413 // Create a dummy time, we'll clear it after ConstructL() returns... |
|
414 TTime now; now.HomeTime(); |
|
415 |
|
416 CMemSpyEngineSinkMetaData* self = new(ELeave) CMemSpyEngineSinkMetaData( aOverwrite, aUseFileTimeStamp ); |
|
417 CleanupStack::PushL( self ); |
|
418 self->ConstructL( aContext, aFolder, aExtension, now ); |
|
419 CleanupStack::Pop( self ); |
|
420 |
|
421 // Clear folder time stamp |
|
422 self->iFolderTimeStamp->Des().Zero(); |
|
423 return self; |
|
424 } |
|
425 |
|
426 |
|
427 EXPORT_C CMemSpyEngineSinkMetaData* CMemSpyEngineSinkMetaData::NewL( const TDesC& aContext, const TDesC& aFolder, const TDesC& aExtension, TBool aOverwrite, TBool aUseFileTimeStamp, const TTime& aFolderTimeStamp ) |
|
428 { |
|
429 CMemSpyEngineSinkMetaData* self = new(ELeave) CMemSpyEngineSinkMetaData( aOverwrite, aUseFileTimeStamp ); |
|
430 CleanupStack::PushL( self ); |
|
431 self->ConstructL( aContext, aFolder, aExtension, aFolderTimeStamp ); |
|
432 CleanupStack::Pop( self ); |
|
433 return self; |
|
434 } |
|
435 |
|
436 |