|
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <cnode.h> |
|
17 |
|
18 #ifndef __WAP_MONOLITHIC__ |
|
19 // Its a standalone DLL |
|
20 |
|
21 #ifndef EKA2 |
|
22 GLDEF_C TInt E32Dll(TDllReason /*aReason*/) |
|
23 { |
|
24 return(KErrNone); |
|
25 } |
|
26 #endif |
|
27 |
|
28 #endif |
|
29 // |
|
30 // Node implementation |
|
31 // |
|
32 |
|
33 /** Allocates and constructs a new node. |
|
34 |
|
35 @return New node |
|
36 @param aType The type of the node |
|
37 @param aParent The parent of this node |
|
38 */ |
|
39 EXPORT_C CNode* CNode::NewL(TAny* aType,CNode* aParent) |
|
40 { |
|
41 return (new(ELeave) CNode(aType,aParent)); |
|
42 } |
|
43 |
|
44 CNode::CNode(TAny* aType,CNode* aParent) |
|
45 : iType(aType), iParent(aParent), iValues(8), iTypes(8) |
|
46 {} |
|
47 |
|
48 /** Destructor. |
|
49 |
|
50 Data (if owned by the object), child nodes and attributes are deleted. |
|
51 */ |
|
52 EXPORT_C CNode::~CNode() |
|
53 { |
|
54 iValues.ResetAndDestroy(); |
|
55 delete iDataValue; |
|
56 DeleteAllChildNodes(); |
|
57 } |
|
58 |
|
59 /** Deletes a specified child node. |
|
60 |
|
61 @param aNode Node to delete |
|
62 */ |
|
63 EXPORT_C void CNode::DeleteChildNode(CNode* aNode) |
|
64 { |
|
65 __ASSERT_DEBUG(iChildList != NULL && aNode != NULL ,Panic(ENodeNoChildren)); |
|
66 __ASSERT_DEBUG(aNode != NULL ,Panic(ENodeBadArgument)); |
|
67 CArrayPtr<CNode> &childList = *iChildList; |
|
68 TInt childListCount = iChildList->Count() - 1; |
|
69 for(TInt childIter = childListCount;childIter >= 0;childIter--) |
|
70 { |
|
71 if(aNode == childList[childIter]) |
|
72 { |
|
73 delete childList[childIter]; |
|
74 iChildList->Delete(childIter); |
|
75 break; |
|
76 } |
|
77 |
|
78 } |
|
79 } |
|
80 |
|
81 /** Deletes all the child nodes of this node. |
|
82 */ |
|
83 EXPORT_C void CNode::DeleteAllChildNodes() |
|
84 { |
|
85 if(iChildList != NULL) |
|
86 { |
|
87 iChildList->ResetAndDestroy(); |
|
88 delete iChildList; |
|
89 iChildList = NULL; |
|
90 } |
|
91 } |
|
92 |
|
93 /** Creates a new child node. |
|
94 |
|
95 @return The new child node |
|
96 @param aType Node type |
|
97 */ |
|
98 EXPORT_C CNode& CNode::AppendNodeL(TAny* aType) |
|
99 { |
|
100 CNode* node = CNode::NewL(aType,this); |
|
101 CleanupStack::PushL(node); |
|
102 AppendNodeToThisNodeL(node); |
|
103 CleanupStack::Pop(); |
|
104 return *node; |
|
105 } |
|
106 |
|
107 /** Adds an existing node as a child. |
|
108 |
|
109 @param aNode Node to make a child |
|
110 */ |
|
111 EXPORT_C void CNode::AppendNodeToThisNodeL(CNode* aNode) |
|
112 { |
|
113 if(!iChildList) |
|
114 iChildList = new (ELeave) CArrayPtrFlat<CNode>(KGranularity); |
|
115 iChildList->AppendL(aNode); |
|
116 } |
|
117 |
|
118 /** Gets the first child or the next child after a specified child. |
|
119 |
|
120 @return First or next child node |
|
121 @param aNode Child node or NULL to get the first child |
|
122 */ |
|
123 EXPORT_C CNode* CNode::NextChild(const CNode* aNode) const |
|
124 { |
|
125 // __ASSERT_DEBUG(iChildList != NULL,Panic(ENodeNoChildren)); |
|
126 if(iChildList) //if there are any children |
|
127 { |
|
128 if(aNode == NULL) //if just want the first child |
|
129 return (*iChildList)[0]; |
|
130 else |
|
131 { |
|
132 TInt index = FindChild(aNode); |
|
133 __ASSERT_DEBUG(index != KErrNotFound,Panic(ENodeBadArgument)); |
|
134 // __ASSERT_DEBUG(!((index + 1) >= iChildList->Count()),Panic(ENodeBadArgument)); |
|
135 if(index == KErrNotFound || ((index+1) >= iChildList->Count()) ) |
|
136 return NULL; |
|
137 else |
|
138 return (*iChildList)[index + 1]; |
|
139 } |
|
140 } |
|
141 return NULL; |
|
142 } |
|
143 |
|
144 TInt CNode::FindChild(const CNode* aNode) const |
|
145 { |
|
146 __ASSERT_DEBUG(aNode != NULL, Panic(ENodeBadArgument)); |
|
147 __ASSERT_DEBUG(iChildList != NULL,Panic(ENodeNoChildren)); |
|
148 TInt count = iChildList->Count(); |
|
149 for(TInt childIter = 0;childIter < count; childIter++) |
|
150 { |
|
151 if(aNode == (*iChildList)[childIter]) |
|
152 return childIter; |
|
153 } |
|
154 return KErrNotFound; |
|
155 } |
|
156 |
|
157 /** Gets the previous child before a specified child. |
|
158 |
|
159 @return Previous child node |
|
160 @param aNode Child node |
|
161 */ |
|
162 EXPORT_C CNode* CNode::PrevChild(const CNode& aNode) const |
|
163 { |
|
164 __ASSERT_DEBUG(iChildList != NULL,Panic(ENodeNoChildren)); |
|
165 if(iChildList) //if there are any children |
|
166 { |
|
167 TInt index = FindChild(&aNode); |
|
168 __ASSERT_DEBUG(index != KErrNotFound && index != 0,Panic(ENodeBadArgument)); |
|
169 return (*iChildList)[index - 1]; |
|
170 } |
|
171 else |
|
172 return NULL; |
|
173 } |
|
174 |
|
175 /** Gets the parent of this node. |
|
176 |
|
177 @return Parent |
|
178 */ |
|
179 EXPORT_C CNode* CNode::Parent() const |
|
180 { |
|
181 return iParent; |
|
182 } |
|
183 |
|
184 /** Changes the parent of the node. |
|
185 |
|
186 The node is removed from the childlist of its current parent. |
|
187 |
|
188 @param aParent New parent |
|
189 */ |
|
190 EXPORT_C void CNode::ReparentL(CNode* aParent) |
|
191 { |
|
192 // __ASSERT_DEBUG(iParent != NULL && iParent->iChildList != NULL,Panic(ENodeNoChildren)); |
|
193 if( iParent != NULL && iParent->iChildList != NULL ) |
|
194 { |
|
195 for(TInt ChildIter = 0;ChildIter < iParent->iChildList->Count(); ChildIter++) |
|
196 { |
|
197 if(this == (*iParent->iChildList)[ChildIter]) |
|
198 { |
|
199 iParent->iChildList->Delete(ChildIter); |
|
200 break; |
|
201 } |
|
202 } |
|
203 } |
|
204 if (aParent) |
|
205 { |
|
206 aParent->AppendNodeToThisNodeL(this); |
|
207 iParent = aParent; |
|
208 } |
|
209 } |
|
210 |
|
211 /** Gets the next sibling node. |
|
212 |
|
213 This asks for the next child of its parent. |
|
214 |
|
215 @return Next sibling node |
|
216 */ |
|
217 EXPORT_C CNode* CNode::NextSibling() const |
|
218 { |
|
219 __ASSERT_DEBUG(iParent != NULL,Panic(ENodeNoChildren)); |
|
220 if(iParent) |
|
221 return Parent()->NextChild(this); |
|
222 else |
|
223 return NULL; |
|
224 } |
|
225 |
|
226 /** Gets the previous sibling node. |
|
227 |
|
228 This asks for the previous child of its parent. |
|
229 |
|
230 @return Previous sibling node |
|
231 */ |
|
232 EXPORT_C CNode* CNode::PrevSibling() const |
|
233 { |
|
234 __ASSERT_DEBUG(iParent != NULL,Panic(ENodeNoChildren)); |
|
235 if(iParent) |
|
236 return Parent()->PrevChild(*this); |
|
237 else |
|
238 return NULL; |
|
239 } |
|
240 |
|
241 /** Gets the number of children of this node. |
|
242 |
|
243 @return Number of children of this node |
|
244 */ |
|
245 EXPORT_C TInt CNode::NumberImmediateChildren() const |
|
246 { |
|
247 if(iChildList) |
|
248 return iChildList->Count(); |
|
249 else |
|
250 return 0; |
|
251 } |
|
252 |
|
253 /** Gets the absolute root node of the tree. |
|
254 |
|
255 @return Root node |
|
256 */ |
|
257 EXPORT_C const CNode& CNode::Root() const |
|
258 { |
|
259 const CNode* node = this; |
|
260 while(node->Parent() != NULL) |
|
261 node = node->Parent(); |
|
262 return *node; |
|
263 } |
|
264 |
|
265 /** Sets the node data. |
|
266 |
|
267 The object will delete the data in its destructor. |
|
268 |
|
269 @param aData Node data |
|
270 */ |
|
271 EXPORT_C void CNode::SetDataL(HBufC16* aData) |
|
272 { |
|
273 delete iDataValue; |
|
274 iDataValue=NULL; |
|
275 iDataValue = new(ELeave) CDataDelete(aData); |
|
276 } |
|
277 |
|
278 HBufC16* CNode::SetupDeletableOrNonDeleteableDataLC() |
|
279 { |
|
280 __ASSERT_DEBUG(iDataValue != NULL ,Panic(ENoData)); |
|
281 HBufC16* aData = iDataValue->SetData(NULL); |
|
282 CleanupStack::PushL(aData); // **** eeek ! |
|
283 delete iDataValue; |
|
284 return aData; |
|
285 } |
|
286 |
|
287 /** Sets the object not to delete the node data in its destructor. |
|
288 |
|
289 Note that the function internally reallocates memory. If it leaves, the data is lost. |
|
290 */ |
|
291 EXPORT_C void CNode::SetDataNoDeleteL() |
|
292 { |
|
293 HBufC16* aData = SetupDeletableOrNonDeleteableDataLC(); |
|
294 iDataValue = new (ELeave) CDataNoDelete(aData); |
|
295 CleanupStack::Pop(); |
|
296 } |
|
297 |
|
298 /** Sets the object to delete the node data in its destructor. |
|
299 |
|
300 Note that the function internally reallocates memory. If it leaves, the data is lost. */ |
|
301 EXPORT_C void CNode::ClearSetDataNoDeleteL() |
|
302 { |
|
303 HBufC16* aData = SetupDeletableOrNonDeleteableDataLC(); |
|
304 iDataValue = new (ELeave) CDataDelete(aData); |
|
305 CleanupStack::Pop(); |
|
306 } |
|
307 |
|
308 /** Sets the node data to be taken from a specified file. |
|
309 |
|
310 If the data is deleted, the referenced file is also deleted. |
|
311 |
|
312 @param aFileDataLocationNowNodeOwns Name of the file containing the data |
|
313 */ |
|
314 EXPORT_C void CNode::SetFileDataL(HBufC16* aFileDataLocationNowNodeOwns) |
|
315 { |
|
316 delete iDataValue; |
|
317 iDataValue = NULL; |
|
318 iDataValue = new(ELeave) CFileDataDelete(aFileDataLocationNowNodeOwns); |
|
319 } |
|
320 |
|
321 /** Resets the node data to a specified pointer. |
|
322 |
|
323 Existing data owned by the node is deleted. |
|
324 |
|
325 @param aData Root node |
|
326 */ |
|
327 EXPORT_C void CNode::ResetDataPointer(HBufC16* aData) |
|
328 { |
|
329 if (iDataValue) |
|
330 iDataValue->ResetDataPointer(aData); |
|
331 } |
|
332 |
|
333 /** Gets the node data. |
|
334 |
|
335 @return Node data or NULL if no data is set |
|
336 */ |
|
337 EXPORT_C HBufC16* CNode::Data() const |
|
338 { |
|
339 if(iDataValue) |
|
340 return iDataValue->Data(); |
|
341 else |
|
342 return NULL; |
|
343 } |
|
344 |
|
345 /** Adds an attribute. |
|
346 |
|
347 The node takes ownership of aAttributeValue. |
|
348 |
|
349 @param aAttributeType Attribute type |
|
350 @param aAttributeValue Attribute value |
|
351 */ |
|
352 EXPORT_C void CNode::AddAttributeL(TAny* aAttributeType, CBase* aAttributeValue) |
|
353 { |
|
354 TInt count; |
|
355 if((count=iValues.Count())>0) |
|
356 { |
|
357 const TInt32* typesPtr=iTypesBasePtr; |
|
358 for(TInt ii=0;ii<count;ii++) |
|
359 { |
|
360 if(*typesPtr==(TInt32)aAttributeType) |
|
361 { |
|
362 delete iValues[ii]; |
|
363 iValues[ii]=aAttributeValue; |
|
364 return; |
|
365 } |
|
366 typesPtr++; |
|
367 } |
|
368 } |
|
369 iTypes.AppendL(aAttributeType); |
|
370 TRAPD(err,iValues.AppendL(aAttributeValue)); |
|
371 if(err) |
|
372 iTypes.Delete(iTypes.Count()-1); |
|
373 AdjustBasePointers(); |
|
374 User::LeaveIfError(err); |
|
375 } |
|
376 |
|
377 void CNode::AdjustBasePointers() |
|
378 { |
|
379 if(iValues.Count()) |
|
380 iTypesBasePtr=(TInt32*)iTypes.CArrayFixBase::At(0); |
|
381 else |
|
382 iTypesBasePtr=NULL; |
|
383 } |
|
384 |
|
385 /** Sets node data and adds an attribute. |
|
386 |
|
387 The node takes ownership of aDataand aAttributeValue. |
|
388 Existing node data owned by the node is deleted. |
|
389 |
|
390 @param aData Node data |
|
391 @param aAttributeType Attribute type |
|
392 @param aAttributeValue Attribute value |
|
393 */ |
|
394 EXPORT_C void CNode::AddDataAndAttributeL(HBufC16 *aData, TAny* aAttributeType, CBase* aAttributeValue) |
|
395 { |
|
396 __ASSERT_DEBUG(aData != NULL, Panic(ENodeBadArgument)); |
|
397 |
|
398 delete iDataValue; |
|
399 iDataValue = NULL; |
|
400 iDataValue = new(ELeave) CDataDelete(aData); |
|
401 |
|
402 AddAttributeL(aAttributeType,aAttributeValue); |
|
403 } |
|
404 |
|
405 /** Gets a child node by index. |
|
406 |
|
407 @return Child node |
|
408 @param aByIndex Index of the child node |
|
409 */ |
|
410 EXPORT_C CNode* CNode::Child(TInt aByIndex) const |
|
411 { |
|
412 __ASSERT_DEBUG(iChildList != NULL , Panic(ENodeNoChildren)); |
|
413 __ASSERT_DEBUG(aByIndex < iChildList->Count() && aByIndex >= 0, Panic(ENodeBadArgument)); |
|
414 return ((*iChildList)[aByIndex]); |
|
415 } |
|
416 |
|
417 /** Gets an attribute value for a specified attribute type. |
|
418 |
|
419 @return Attribute value |
|
420 @param aAttributeType Attribute type |
|
421 */ |
|
422 EXPORT_C CBase* CNode::Attribute(TAny* aAttributeType) const |
|
423 { |
|
424 TInt count; |
|
425 if((count=iValues.Count())>0) |
|
426 { |
|
427 const TInt32* typesPtr=iTypesBasePtr; |
|
428 for(TInt ii=0;ii<count;ii++) |
|
429 { |
|
430 if(*typesPtr==(TInt32)aAttributeType) |
|
431 return iValues[ii]; |
|
432 typesPtr++; |
|
433 } |
|
434 } |
|
435 return NULL; |
|
436 } |
|
437 |
|
438 /** Tests if an attribute of a specified type exists. |
|
439 |
|
440 @return True if the attribute exists, otherwise false |
|
441 @param aAttributeType Attribute type |
|
442 */ |
|
443 EXPORT_C TBool CNode::AttributeExists(TAny* aAttributeType) const |
|
444 { |
|
445 TInt count; |
|
446 if((count=iValues.Count())>0) |
|
447 { |
|
448 const TInt32* typesPtr=iTypesBasePtr; |
|
449 for(TInt ii=0;ii<count;ii++) |
|
450 { |
|
451 if(*typesPtr==(TInt32)aAttributeType) |
|
452 return ETrue; |
|
453 typesPtr++; |
|
454 } |
|
455 } |
|
456 return EFalse; |
|
457 } |
|
458 |
|
459 /** Deletes an attribute of a specified type. |
|
460 |
|
461 Note that the attribute value will be deleted. |
|
462 |
|
463 @param aAttributeType Attribute type |
|
464 */ |
|
465 EXPORT_C void CNode::DeleteAttribute(TAny* aAttributeType) |
|
466 { |
|
467 TInt count; |
|
468 if((count=iValues.Count())>0) |
|
469 { |
|
470 const TInt32* typesPtr=iTypesBasePtr; |
|
471 for(TInt ii=0;ii<count;ii++) |
|
472 { |
|
473 if(*typesPtr==(TInt32)aAttributeType) |
|
474 { // delete attribute value |
|
475 delete iValues[ii]; |
|
476 iValues.Delete(ii); |
|
477 iTypes.Delete(ii); |
|
478 AdjustBasePointers(); |
|
479 break; |
|
480 } |
|
481 typesPtr++; |
|
482 } |
|
483 } |
|
484 } |
|
485 |
|
486 /** Delete all node attributes. |
|
487 |
|
488 Note that attribute values will be deleted. |
|
489 */ |
|
490 EXPORT_C void CNode::DeleteAllAttributes() |
|
491 { |
|
492 iValues.ResetAndDestroy(); |
|
493 iTypes.Reset(); |
|
494 AdjustBasePointers(); |
|
495 } |
|
496 |
|
497 /** Removes an attribute of a specified type, but does not delete it. |
|
498 |
|
499 The caller is now responsible for the destruction of the attribute value. |
|
500 |
|
501 @param aAttributeType Attribute type |
|
502 */ |
|
503 EXPORT_C void CNode::RemoveAttributeNoDelete(TAny* aAttributeType) |
|
504 { |
|
505 TInt count; |
|
506 if((count=iValues.Count())>0) |
|
507 { |
|
508 const TInt32* typesPtr=iTypesBasePtr; |
|
509 for(TInt ii=0;ii<count;ii++) |
|
510 { |
|
511 if(*typesPtr==(TInt32)aAttributeType) |
|
512 { // do not delete the pointer in iValues |
|
513 iValues.Delete(ii); |
|
514 iTypes.Delete(ii); |
|
515 AdjustBasePointers(); |
|
516 break; |
|
517 } |
|
518 typesPtr++; |
|
519 } |
|
520 } |
|
521 } |
|
522 |
|
523 /** Gets the number of attributes of this node. |
|
524 |
|
525 @return Number of attributes of this node |
|
526 */ |
|
527 EXPORT_C TInt CNode::AttributeCount() const |
|
528 { |
|
529 return iValues.Count(); |
|
530 } |
|
531 |
|
532 /** Gets the attribute value of an attribute at a specified index. |
|
533 |
|
534 @return Attribute value |
|
535 @param aIndex Attribute index |
|
536 */ |
|
537 EXPORT_C CBase* CNode::AttributeByIndex(TInt aIndex) const |
|
538 { |
|
539 if(iValues.Count()) |
|
540 return iValues[aIndex]; |
|
541 return NULL; |
|
542 } |
|
543 |
|
544 /** Gets the attribute value and type of an attribute at a specified index.. |
|
545 |
|
546 @return Attribute value |
|
547 @param aIndex Attribute index |
|
548 @param aType On return, the attribute type |
|
549 */ |
|
550 EXPORT_C CBase* CNode::AttributeByIndex(TInt aIndex,TAny*& aType) const |
|
551 { |
|
552 if(iValues.Count()) |
|
553 { |
|
554 aType=iTypes[aIndex]; |
|
555 return iValues[aIndex]; |
|
556 } |
|
557 return NULL; |
|
558 } |
|
559 |
|
560 /** Gets the attribute value of an attribute at a specified index |
|
561 |
|
562 @return Attribute value |
|
563 @param aIndex Attribute index |
|
564 */ |
|
565 EXPORT_C TAny* CNode::AttributeTypeByIndex(TInt aIndex) const |
|
566 { |
|
567 if(iValues.Count()) |
|
568 return iTypes[aIndex]; |
|
569 return NULL; |
|
570 } |
|
571 |
|
572 /** Gets the node type. |
|
573 |
|
574 @return Node type |
|
575 */ |
|
576 EXPORT_C TAny* CNode::Type() const |
|
577 { |
|
578 return iType; |
|
579 } |
|
580 |
|
581 /** Sets the node type. |
|
582 |
|
583 @param aType Node type |
|
584 */ |
|
585 EXPORT_C void CNode::SetType(TAny* aType) |
|
586 { |
|
587 iType = aType; |
|
588 } |
|
589 |
|
590 void CNode::Reserved1() |
|
591 // Reserved for future expansion |
|
592 { |
|
593 User::Panic(_L("Reserved"),KErrNotSupported); |
|
594 } |
|
595 |
|
596 void CNode::Reserved1() const |
|
597 // Reserved for future expansion |
|
598 { |
|
599 User::Panic(_L("Reserved"),KErrNotSupported); |
|
600 } |