|
1 /* |
|
2 * Copyright (c) 2004 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: XML Serializer implementation. |
|
15 * |
|
16 */ |
|
17 |
|
18 // INCLUDE FILES |
|
19 #include "CPEngXmlSerializer.h" |
|
20 #include "PEngXmlDefs.h" |
|
21 #include "PresenceDebugPrint.h" |
|
22 |
|
23 |
|
24 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
25 #include "CPEngTagAssertionStack.h" |
|
26 #endif |
|
27 |
|
28 #include <E32Std.h> |
|
29 #include <utf.h> |
|
30 #include <imcvcodc.h> |
|
31 |
|
32 |
|
33 |
|
34 //CONSTANTS |
|
35 /** |
|
36 * State stack granularity. |
|
37 * State stack has great size |
|
38 * variety depending from use case. |
|
39 * 5 should be quite optimal. |
|
40 */ |
|
41 const TInt KStackGranurality = 5; |
|
42 |
|
43 /** |
|
44 * WV schema prefix & length. |
|
45 */ |
|
46 _LIT( KWVSchemaPrefix, "wv:" ); |
|
47 const TInt KWVSchemaPrefixLength = 3; |
|
48 |
|
49 // ================= LOCAL FUNCTIONS ======================= |
|
50 /** |
|
51 * Serializer panic implementation. |
|
52 */ |
|
53 #if defined(_DEBUG) |
|
54 GLREF_C void PanicSerializer( TPEngSerializerPanics aReason ) |
|
55 { |
|
56 User::Panic( KXmlSerializer, aReason ); |
|
57 } |
|
58 #else |
|
59 GLREF_C void PanicSerializer( TPEngSerializerPanics /*aReason*/ ) |
|
60 { |
|
61 } |
|
62 #endif |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 // ================= MEMBER FUNCTIONS ======================= |
|
68 // Two-phased constructor. |
|
69 CPEngXmlSerializer* CPEngXmlSerializer::NewL( TDes8& aBuffer ) |
|
70 { |
|
71 CPEngXmlSerializer* self = CPEngXmlSerializer::NewLC( aBuffer ); |
|
72 CleanupStack::Pop( self ); |
|
73 return self; |
|
74 } |
|
75 |
|
76 |
|
77 |
|
78 CPEngXmlSerializer* CPEngXmlSerializer::NewLC( TDes8& aBuffer ) |
|
79 { |
|
80 CPEngXmlSerializer* self = new ( ELeave ) CPEngXmlSerializer( aBuffer ); |
|
81 |
|
82 CleanupStack::PushL( self ); |
|
83 self->ConstructL(); |
|
84 |
|
85 return self; |
|
86 } |
|
87 |
|
88 // Destructor |
|
89 CPEngXmlSerializer::~CPEngXmlSerializer() |
|
90 { |
|
91 iStateStack.Reset(); |
|
92 |
|
93 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
94 delete iAssertionStack; |
|
95 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
96 |
|
97 |
|
98 #if _BullseyeCoverage |
|
99 cov_write(); |
|
100 #endif |
|
101 } |
|
102 |
|
103 |
|
104 // C++ default constructor can NOT contain any code, that |
|
105 // might leave. |
|
106 // |
|
107 CPEngXmlSerializer::CPEngXmlSerializer( TDes8& aBuffer ) |
|
108 : iState( EPEngInRoot ), |
|
109 iWriter( aBuffer ), |
|
110 iStartTagCount( 0 ), |
|
111 iStateStack( KStackGranurality ) |
|
112 { |
|
113 } |
|
114 |
|
115 |
|
116 // Symbian OS default constructor can leave. |
|
117 void CPEngXmlSerializer::ConstructL() |
|
118 { |
|
119 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
120 iAssertionStack = CPEngTagAssertionStack::NewL( KStackGranurality ); |
|
121 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
122 } |
|
123 |
|
124 |
|
125 |
|
126 // ----------------------------------------------------------------------------- |
|
127 // CPEngXmlSerializer::Close() |
|
128 // ----------------------------------------------------------------------------- |
|
129 // |
|
130 void CPEngXmlSerializer::Close() |
|
131 { |
|
132 delete this; |
|
133 } |
|
134 |
|
135 |
|
136 // ----------------------------------------------------------------------------- |
|
137 // CPEngXmlSerializer::StartTagL() |
|
138 // ----------------------------------------------------------------------------- |
|
139 // |
|
140 MPEngXMLSerializer& CPEngXmlSerializer::StartTagL( const TDesC8& aName ) |
|
141 { |
|
142 //tag name may not be empty |
|
143 __AssertNotEmptyL( aName ); |
|
144 |
|
145 |
|
146 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
147 //make sure that if we can write the start tag, |
|
148 //we get it surely to element stack also |
|
149 iAssertionStack->ReserveOneL(); |
|
150 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
151 |
|
152 |
|
153 CheckAndCloseOpenStartTagL(); //goes to EElementOpen state |
|
154 iWriter.WriteL( KXmlTagStart ); |
|
155 |
|
156 |
|
157 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
158 TPtrC8 writtenTag( iWriter.WriteL( aName ) ); |
|
159 iAssertionStack->PushL( writtenTag ); //won't fail, see previous ReserveOneL() |
|
160 #else |
|
161 iWriter.WriteL( aName ); |
|
162 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
163 |
|
164 iStartTagCount++; |
|
165 iState = EPEngInStartTag; |
|
166 |
|
167 return *this; |
|
168 } |
|
169 |
|
170 |
|
171 |
|
172 // ----------------------------------------------------------------------------- |
|
173 // CPEngXmlSerializer::AttributeL() |
|
174 // ----------------------------------------------------------------------------- |
|
175 // |
|
176 MPEngXMLSerializer& CPEngXmlSerializer::AttributeL( const TDesC8& aName, |
|
177 const TDesC8& aValue ) |
|
178 { |
|
179 //attribute can be written only just after the start tag. |
|
180 __AssertSerializerStateL( ( iState == EPEngInStartTag ), |
|
181 EPEngSrlzr_AttributeNotAllowed ); |
|
182 |
|
183 //attribute name may not be empty |
|
184 __AssertNotEmptyL( aName ); |
|
185 |
|
186 |
|
187 iWriter.WriteL( KXmlWhiteSpace ); |
|
188 iWriter.WriteL( aName ); |
|
189 iWriter.WriteL( KXmlEqualSign ); |
|
190 |
|
191 TBuf8< 1 > quote; //quote is one character, either ' or " |
|
192 quote = KXmlApostrophe; |
|
193 if ( aValue.Find( KXmlDoubleQuote ) == KErrNotFound ) |
|
194 { |
|
195 quote = KXmlDoubleQuote; |
|
196 } |
|
197 |
|
198 iWriter.WriteL( quote ); |
|
199 WriteXmlEscapedL( aValue, ETrue ); |
|
200 iWriter.WriteL( quote ); |
|
201 |
|
202 |
|
203 return *this; |
|
204 } |
|
205 |
|
206 |
|
207 |
|
208 // ----------------------------------------------------------------------------- |
|
209 // CPEngXmlSerializer::EndTagL() |
|
210 // ----------------------------------------------------------------------------- |
|
211 // |
|
212 MPEngXMLSerializer& CPEngXmlSerializer::EndTagL( const TDesC8& aName ) |
|
213 { |
|
214 //Check there is start tag to close |
|
215 __AssertSerializerStateL( ( ( iState == EPEngInStartTag ) || ( iState == EPEngInElement ) ), |
|
216 EPEngSrlzr_EndTagNotAllowed ); |
|
217 |
|
218 //tag name may not be empty |
|
219 __AssertNotEmptyL( aName ); |
|
220 |
|
221 |
|
222 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
223 //Check end tag name match corresponding start tag name |
|
224 __AssertEndTagName( aName ); |
|
225 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
226 |
|
227 |
|
228 |
|
229 if ( iState == EPEngInStartTag ) |
|
230 { |
|
231 //still in start tag ==> empty element ==> close the tag directly |
|
232 iWriter.WriteL( KXmlEmptyTagEnd ); |
|
233 } |
|
234 |
|
235 |
|
236 else |
|
237 { |
|
238 //non empty element ==> write complete end tag |
|
239 iWriter.WriteL( KXmlEndTagStart ); |
|
240 iWriter.WriteL( aName ); |
|
241 iWriter.WriteL( KXmlTagEnd ); |
|
242 } |
|
243 |
|
244 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
245 iAssertionStack->Pop(); |
|
246 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
247 |
|
248 |
|
249 iStartTagCount--; |
|
250 if ( iStartTagCount == 0 ) |
|
251 { |
|
252 //closed the last open element ==> now in root |
|
253 iState = EPEngInRoot; |
|
254 } |
|
255 else |
|
256 { |
|
257 //there is still not closed start tags ==> open elements |
|
258 iState = EPEngInElement; |
|
259 } |
|
260 |
|
261 |
|
262 return *this; |
|
263 } |
|
264 |
|
265 |
|
266 // ----------------------------------------------------------------------------- |
|
267 // CPEngXmlSerializer::RawValueL() |
|
268 // ----------------------------------------------------------------------------- |
|
269 // |
|
270 MPEngXMLSerializer& CPEngXmlSerializer::RawValueL( const TDesC8& aValue ) |
|
271 { |
|
272 //Write raw data |
|
273 |
|
274 CheckAndCloseOpenStartTagL(); //goes to EElementOpen state |
|
275 |
|
276 __AssertNoXmlEscapedCharsL( aValue ); |
|
277 |
|
278 iWriter.WriteL( aValue ); |
|
279 |
|
280 return *this; |
|
281 } |
|
282 |
|
283 |
|
284 // ----------------------------------------------------------------------------- |
|
285 // CPEngXmlSerializer::NarrowTextL() |
|
286 // ----------------------------------------------------------------------------- |
|
287 // |
|
288 MPEngXMLSerializer& CPEngXmlSerializer::NarrowTextL( const TDesC8& aText ) |
|
289 { |
|
290 // Performed steps: |
|
291 // 1. Escapes XML entities. |
|
292 |
|
293 |
|
294 CheckAndCloseOpenStartTagL(); //goes to EElementOpen state |
|
295 |
|
296 WriteXmlEscapedL( aText, EFalse ); |
|
297 return *this; |
|
298 } |
|
299 |
|
300 |
|
301 |
|
302 // ----------------------------------------------------------------------------- |
|
303 // CPEngXmlSerializer::UnicodeTextL() |
|
304 // ----------------------------------------------------------------------------- |
|
305 // |
|
306 MPEngXMLSerializer& CPEngXmlSerializer::UnicodeTextL( const TDesC16& aText ) |
|
307 { |
|
308 // Performed steps: |
|
309 // 1. Converts text from Unicode to Utf8 |
|
310 // 2. Escapes XML entities |
|
311 |
|
312 TBuf8<20> outputBuffer; |
|
313 TPtrC16 remainderOfUnicodeText( aText ); |
|
314 TInt returnValue; |
|
315 |
|
316 CheckAndCloseOpenStartTagL(); //goes to EElementOpen state |
|
317 |
|
318 |
|
319 FOREVER // conversion loop |
|
320 { |
|
321 returnValue = CnvUtfConverter::ConvertFromUnicodeToUtf8( outputBuffer, |
|
322 remainderOfUnicodeText ); |
|
323 |
|
324 // check to see that the descriptor isn’t corrupt |
|
325 if ( returnValue == CnvUtfConverter::EErrorIllFormedInput ) |
|
326 { |
|
327 User::Leave( KErrCorrupt ); |
|
328 } |
|
329 |
|
330 else if ( returnValue < KErrNone ) // future-proof against "TError" expanding |
|
331 // See SDK help for more information. |
|
332 { |
|
333 User::Leave( KErrGeneral ); |
|
334 } |
|
335 |
|
336 //write the Utf8 fragment produced by this round |
|
337 WriteXmlEscapedL( outputBuffer, EFalse ); |
|
338 |
|
339 if ( returnValue == 0 ) |
|
340 { |
|
341 //no more text left -> break the loop |
|
342 break; |
|
343 } |
|
344 |
|
345 remainderOfUnicodeText.Set( remainderOfUnicodeText.Right( returnValue ) ); |
|
346 } |
|
347 |
|
348 return *this; |
|
349 } |
|
350 |
|
351 |
|
352 |
|
353 // ----------------------------------------------------------------------------- |
|
354 // CPEngXmlSerializer::WvAddressL() |
|
355 // ----------------------------------------------------------------------------- |
|
356 // |
|
357 MPEngXMLSerializer& CPEngXmlSerializer::WvAddressL( const TDesC16& aAddress ) |
|
358 { |
|
359 // Performed steps: |
|
360 // 1. Escapes WV Address characters |
|
361 // 2. Converts text from Unicode to Utf8 |
|
362 // 3. Escape XML entities |
|
363 |
|
364 |
|
365 TBuf16<20> outputBuffer; |
|
366 TPtrC16 remainderOfAddress( aAddress ); |
|
367 TInt returnValue; |
|
368 |
|
369 CheckAndCloseOpenStartTagL(); //goes to EElementOpen state |
|
370 |
|
371 |
|
372 // Skip the possible "wv:" prefix from address |
|
373 // And write it as it is |
|
374 if ( aAddress.Left( KWVSchemaPrefixLength ).CompareF( KWVSchemaPrefix ) == 0 ) |
|
375 { |
|
376 remainderOfAddress.Set( aAddress.Mid( KWVSchemaPrefixLength ) ); |
|
377 UnicodeTextL( aAddress.Left( KWVSchemaPrefixLength ) ); |
|
378 } |
|
379 |
|
380 FOREVER // conversion loop |
|
381 { |
|
382 returnValue = EncodeWvAddressChars( outputBuffer, |
|
383 remainderOfAddress ); |
|
384 |
|
385 // Handle possible errors |
|
386 if ( returnValue < KErrNone ) |
|
387 { |
|
388 User::Leave( KErrGeneral ); |
|
389 } |
|
390 |
|
391 |
|
392 //write the WVAddress part produced by this round |
|
393 UnicodeTextL( outputBuffer ); |
|
394 |
|
395 |
|
396 if ( returnValue == 0 ) |
|
397 { |
|
398 //no more text left -> break the loop |
|
399 break; |
|
400 } |
|
401 |
|
402 remainderOfAddress.Set( remainderOfAddress.Right( returnValue ) ); |
|
403 } |
|
404 |
|
405 return *this; |
|
406 } |
|
407 |
|
408 |
|
409 |
|
410 // ----------------------------------------------------------------------------- |
|
411 // CPEngXmlSerializer::Base64DataL() |
|
412 // ----------------------------------------------------------------------------- |
|
413 // |
|
414 MPEngXMLSerializer& CPEngXmlSerializer::Base64DataL( const TDesC8& aRawData ) |
|
415 { |
|
416 // Performed steps: |
|
417 // 1. Coverts data to BASE64 format |
|
418 |
|
419 |
|
420 CheckAndCloseOpenStartTagL(); //goes to EElementOpen state |
|
421 |
|
422 if ( aRawData.Length() != 0 ) |
|
423 { |
|
424 TImCodecB64 base64Encoder; |
|
425 base64Encoder.Initialise(); |
|
426 |
|
427 //Encoder doesn't itself cope with buffer overflows, |
|
428 //so allocate twice big buffer to be sure that there is enough |
|
429 //space for B64 data |
|
430 HBufC8* base64Buffer = HBufC8::NewLC( aRawData.Size() * 2 ); |
|
431 TPtr8 base64Data( base64Buffer->Des() ); |
|
432 base64Encoder.Encode( aRawData, base64Data ); |
|
433 |
|
434 |
|
435 //for performance reasons, write |
|
436 //whole base64 data directly to the |
|
437 //xml buffer (no need to do any XML escaping) |
|
438 iWriter.WriteL( base64Data ); |
|
439 CleanupStack::PopAndDestroy(); //base64Buffer |
|
440 } |
|
441 |
|
442 return *this; |
|
443 } |
|
444 |
|
445 |
|
446 // ----------------------------------------------------------------------------- |
|
447 // CPEngXmlSerializer::PushSerializerStateL() |
|
448 // ----------------------------------------------------------------------------- |
|
449 // |
|
450 void CPEngXmlSerializer::PushSerializerStateL() |
|
451 { |
|
452 TPEngSerializerStateData state; |
|
453 state.iWriterLength = iWriter.CurrentLength(); |
|
454 state.iState = iState; |
|
455 |
|
456 |
|
457 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
458 state.iAssertionStackCount = iAssertionStack->Count(); |
|
459 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
460 |
|
461 |
|
462 User::LeaveIfError( iStateStack.Append( state ) ); //push new state to state stack |
|
463 } |
|
464 |
|
465 |
|
466 // ----------------------------------------------------------------------------- |
|
467 // CPEngXmlSerializer::CommitState() |
|
468 // ----------------------------------------------------------------------------- |
|
469 // |
|
470 void CPEngXmlSerializer::CommitState() |
|
471 { |
|
472 //check that there is a states to commit |
|
473 __ASSERT_DEBUG( ( iStateStack.Count() > 0 ), |
|
474 PanicSerializer( EPEngSrlzr_StateStackUnderflow ) ); |
|
475 |
|
476 TInt stateCount( iStateStack.Count() ); |
|
477 if ( stateCount > 0 ) |
|
478 { |
|
479 iStateStack.Remove( stateCount - 1 ); //pop the last state away from state stack (thus -1) |
|
480 } |
|
481 } |
|
482 |
|
483 |
|
484 // ----------------------------------------------------------------------------- |
|
485 // CPEngXmlSerializer::RollbackState() |
|
486 // ----------------------------------------------------------------------------- |
|
487 // |
|
488 void CPEngXmlSerializer::RollbackState() |
|
489 { |
|
490 //Check that there is a states to rollback |
|
491 __ASSERT_DEBUG( ( iStateStack.Count() > 0 ), |
|
492 PanicSerializer( EPEngSrlzr_StateStackUnderflow ) ); |
|
493 |
|
494 TInt stateCount( iStateStack.Count() ); |
|
495 if ( stateCount > 0 ) |
|
496 { |
|
497 TPEngSerializerStateData oldState; |
|
498 oldState = iStateStack[ stateCount - 1 ]; |
|
499 iStateStack.Remove( stateCount - 1 ); //pop the last state away from state stack (thus -1) |
|
500 |
|
501 //rollback writer |
|
502 iWriter.ReverseTo( oldState.iWriterLength ); |
|
503 |
|
504 |
|
505 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
506 //rollback assertion stack |
|
507 iAssertionStack->PopTo( oldState.iAssertionStackCount ); |
|
508 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
509 |
|
510 |
|
511 //return to old state |
|
512 iState = oldState.iState; |
|
513 } |
|
514 } |
|
515 |
|
516 |
|
517 // ----------------------------------------------------------------------------- |
|
518 // CPEngXmlSerializer::PushedStateCount() |
|
519 // ----------------------------------------------------------------------------- |
|
520 // |
|
521 TInt CPEngXmlSerializer::PushedStateCount() |
|
522 { |
|
523 return iStateStack.Count(); |
|
524 } |
|
525 |
|
526 |
|
527 |
|
528 // ----------------------------------------------------------------------------- |
|
529 // CPEngXmlSerializer::CheckAndCloseOpenStartTagL() |
|
530 // ----------------------------------------------------------------------------- |
|
531 // |
|
532 void CPEngXmlSerializer::CheckAndCloseOpenStartTagL() |
|
533 { |
|
534 if ( iState == EPEngInStartTag ) |
|
535 { |
|
536 iWriter.WriteL( KXmlTagEnd ); |
|
537 iState = EPEngInElement; |
|
538 } |
|
539 } |
|
540 |
|
541 |
|
542 |
|
543 |
|
544 // ----------------------------------------------------------------------------- |
|
545 // CPEngXmlSerializer::EncodeWvAddressChars() |
|
546 // Return the number of unconverted characters left at the end of the input |
|
547 // descriptor, or the error value |
|
548 // ----------------------------------------------------------------------------- |
|
549 // |
|
550 TInt CPEngXmlSerializer::EncodeWvAddressChars( TDes16& aEncodedAddress, |
|
551 const TDesC16& aUnicodeAddress ) |
|
552 { |
|
553 if ( aUnicodeAddress.Length() == 0 ) |
|
554 { |
|
555 aEncodedAddress.SetLength( 0 ); |
|
556 return 0; |
|
557 } |
|
558 |
|
559 |
|
560 if ( aEncodedAddress.MaxLength() == 0 ) |
|
561 { |
|
562 return aUnicodeAddress.Length(); |
|
563 } |
|
564 |
|
565 aEncodedAddress.Zero(); |
|
566 |
|
567 TInt addLen( aUnicodeAddress.Length() ); |
|
568 for ( TInt ii( 0 ); ii < addLen; ii++ ) |
|
569 { |
|
570 TUint16 characterValue = aUnicodeAddress[ ii ]; |
|
571 |
|
572 switch ( characterValue ) |
|
573 { |
|
574 case ':': |
|
575 case ';': |
|
576 case '?': |
|
577 case '&': |
|
578 case '=': |
|
579 case '+': |
|
580 case '$': |
|
581 case ',': |
|
582 { |
|
583 TInt spaceLeft = aEncodedAddress.MaxLength() - aEncodedAddress.Length(); |
|
584 |
|
585 //Encoding special characters produces 3 characters e.g. "%yy" |
|
586 //(only three produced because encoded characters list is |
|
587 //limited above) |
|
588 if ( spaceLeft < 3 ) |
|
589 { |
|
590 return addLen - ii; |
|
591 } |
|
592 |
|
593 aEncodedAddress.Append( KPercentSign16 ); |
|
594 aEncodedAddress.AppendNumUC( characterValue, EHex ); |
|
595 break; |
|
596 } |
|
597 |
|
598 default: |
|
599 { |
|
600 TInt spaceLeft = aEncodedAddress.MaxLength() - aEncodedAddress.Length(); |
|
601 |
|
602 //Adding one non-encoded character requires space one character |
|
603 if ( spaceLeft < 1 ) |
|
604 { |
|
605 return addLen - ii; |
|
606 } |
|
607 |
|
608 aEncodedAddress.Append( characterValue ); |
|
609 break; |
|
610 } |
|
611 } |
|
612 } |
|
613 |
|
614 |
|
615 return KErrNone; |
|
616 } |
|
617 |
|
618 |
|
619 |
|
620 |
|
621 |
|
622 // ----------------------------------------------------------------------------- |
|
623 // CPEngXmlSerializer::WriteXmlEscapedL() |
|
624 // ----------------------------------------------------------------------------- |
|
625 // |
|
626 void CPEngXmlSerializer::WriteXmlEscapedL( const TDesC8& aString, |
|
627 TBool aEscapeQuotes ) |
|
628 { |
|
629 const TInt length( aString.Length() ); |
|
630 TUint8 character; |
|
631 |
|
632 //loop trough the all characters and escape them to writer one by one |
|
633 for ( TInt ii( 0 ); ii < length; ii++ ) |
|
634 { |
|
635 character = aString[ ii ]; |
|
636 WriteXmlEscapedL( character, aEscapeQuotes ); |
|
637 } |
|
638 } |
|
639 |
|
640 |
|
641 // ----------------------------------------------------------------------------- |
|
642 // CPEngXmlSerializer::WriteXmlEscapedL() |
|
643 // ----------------------------------------------------------------------------- |
|
644 // |
|
645 void CPEngXmlSerializer::WriteXmlEscapedL( TUint8 aCharacter, |
|
646 TBool aEscapeQuotes ) |
|
647 { |
|
648 switch ( aCharacter ) |
|
649 { |
|
650 case '&': |
|
651 { |
|
652 iWriter.WriteL( KEntityAmpersand ); |
|
653 break; |
|
654 } |
|
655 |
|
656 case '>': |
|
657 { |
|
658 iWriter.WriteL( KEntityGreaterThan ); |
|
659 break; |
|
660 } |
|
661 |
|
662 case '<': |
|
663 { |
|
664 iWriter.WriteL( KEntityLowerThan ); |
|
665 break; |
|
666 } |
|
667 |
|
668 case '"': ///<If character is a double |
|
669 case '\'': ///<or single quote, escape it only if required |
|
670 { |
|
671 if ( aEscapeQuotes ) |
|
672 { |
|
673 if ( aCharacter == '"' ) |
|
674 { |
|
675 iWriter.WriteL( KEntityDoubleQuote ); |
|
676 } |
|
677 else |
|
678 { |
|
679 iWriter.WriteL( KEntityApostrophe ); |
|
680 } |
|
681 |
|
682 break; |
|
683 } |
|
684 |
|
685 //else no need to escape quotes ==> |
|
686 //write them as normal characters |
|
687 //FLOW TROUGH |
|
688 } |
|
689 |
|
690 default: |
|
691 { |
|
692 iWriter.WriteL( aCharacter ); |
|
693 } |
|
694 } |
|
695 } |
|
696 |
|
697 |
|
698 |
|
699 |
|
700 |
|
701 // ----------------------------------------------------------------------------- |
|
702 // CPEngXmlSerializer::__AssertNoXmlEscapedCharsL() |
|
703 // ----------------------------------------------------------------------------- |
|
704 // |
|
705 void CPEngXmlSerializer::__AssertNoXmlEscapedCharsL( const TDesC8& aString ) |
|
706 { |
|
707 const TInt length( aString.Length() ); |
|
708 TUint8 character; |
|
709 |
|
710 //loop trough the all characters and check them |
|
711 for ( TInt ii( 0 ); ii < length; ii++ ) |
|
712 { |
|
713 character = aString[ ii ]; |
|
714 switch ( character ) |
|
715 { |
|
716 case '&': |
|
717 case '>': |
|
718 case '<': |
|
719 case '"': |
|
720 case '\'': |
|
721 { |
|
722 #if defined(_DEBUG) |
|
723 PanicSerializer( EPEngSrlzr_XmlMarkupCharNotAllowed ); |
|
724 #else |
|
725 User::Leave( KErrArgument ); |
|
726 #endif |
|
727 |
|
728 break; |
|
729 } |
|
730 |
|
731 default: |
|
732 { |
|
733 break; |
|
734 } |
|
735 } |
|
736 } |
|
737 } |
|
738 |
|
739 |
|
740 |
|
741 |
|
742 |
|
743 // ----------------------------------------------------------------------------- |
|
744 // CPEngXmlSerializer::__AssertSerializerStateL() |
|
745 // ----------------------------------------------------------------------------- |
|
746 // |
|
747 #if defined(_DEBUG) |
|
748 void CPEngXmlSerializer::__AssertSerializerStateL( TBool aInCorrectState, |
|
749 TPEngSerializerPanics aPanicReason ) |
|
750 #else |
|
751 void CPEngXmlSerializer::__AssertSerializerStateL( TBool aInCorrectState, |
|
752 TPEngSerializerPanics /*aPanicReason*/ ) |
|
753 #endif |
|
754 { |
|
755 if ( !aInCorrectState ) |
|
756 { |
|
757 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
758 TBuf<150> buffer16; //restrict tag names shown in debug output to 150 characters. |
|
759 //150 characters should be enough for debug purposes. |
|
760 |
|
761 TPtrC8 startTagName = iAssertionStack->Top(); |
|
762 buffer16.Copy( startTagName.Left( buffer16.MaxLength() ) ); |
|
763 |
|
764 PENG_DP( D_PENG_LIT( "CPEngXmlSerializer: Wrong state. In tag <%S> at nesting level %i" ), |
|
765 &buffer16, iAssertionStack->Count() ); |
|
766 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
767 |
|
768 |
|
769 #if defined(_DEBUG) |
|
770 PanicSerializer( aPanicReason ); |
|
771 #else |
|
772 User::Leave( KErrNotSupported ); |
|
773 #endif |
|
774 } |
|
775 } |
|
776 |
|
777 |
|
778 // ----------------------------------------------------------------------------- |
|
779 // CPEngXmlSerializer::__AssertNotEmptyL() |
|
780 // ----------------------------------------------------------------------------- |
|
781 // |
|
782 void CPEngXmlSerializer::__AssertNotEmptyL( const TDesC8& aString ) |
|
783 { |
|
784 if ( aString.Length() == 0 ) |
|
785 { |
|
786 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
787 TBuf<150> buffer16; //restrict tag names shown in debug output to 150 characters. |
|
788 //150 characters should be enough for debug purposes. |
|
789 |
|
790 TPtrC8 startTagName = iAssertionStack->Top(); |
|
791 buffer16.Copy( startTagName.Left( buffer16.MaxLength() ) ); |
|
792 |
|
793 PENG_DP( D_PENG_LIT( "CPEngXmlSerializer: Writing empty tag or attribute. In tag <%S> at nesting level %i" ), |
|
794 &buffer16, iAssertionStack->Count() ); |
|
795 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
796 |
|
797 |
|
798 #if defined(_DEBUG) |
|
799 PanicSerializer( EPEngSrlzr_EmptyInputString ); |
|
800 #else |
|
801 User::Leave( KErrArgument ); |
|
802 #endif |
|
803 } |
|
804 } |
|
805 |
|
806 |
|
807 #ifdef __SERIALIZER_TAG_NAME_ASSERT |
|
808 // ----------------------------------------------------------------------------- |
|
809 // CPEngXmlSerializer::__AssertEndTagName() |
|
810 // ----------------------------------------------------------------------------- |
|
811 // |
|
812 void CPEngXmlSerializer::__AssertEndTagName( const TDesC8& aEndTagName ) |
|
813 { |
|
814 if ( aEndTagName != iAssertionStack->Top() ) |
|
815 { |
|
816 TBuf<150> buffer16; //restrict tag names shown in debug output to 150 characters. |
|
817 //150 characters should be enough for debug purposes. |
|
818 |
|
819 buffer16.Copy( aEndTagName.Left( buffer16.MaxLength() ) ); |
|
820 PENG_DP( D_PENG_LIT( "CPEngXmlSerializer: End tag mismatch. Ending with <%S> at level %i" ), |
|
821 &buffer16, iAssertionStack->Count() ); |
|
822 |
|
823 buffer16.Zero(); |
|
824 TPtrC8 startTagName = iAssertionStack->Top(); |
|
825 buffer16.Copy( startTagName.Left( buffer16.MaxLength() ) ); |
|
826 PENG_DP( D_PENG_LIT( "CPEngXmlSerializer: Required start tag <%S>" ), |
|
827 &buffer16 ); |
|
828 |
|
829 PanicSerializer( EPEngSrlzr_EndTagNameMismatch ); |
|
830 } |
|
831 } |
|
832 #endif // __SERIALIZER_TAG_NAME_ASSERT |
|
833 |
|
834 |
|
835 // End of File |
|
836 |
|
837 |
|
838 |
|
839 |