cleanups and comments.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34849 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2012-03-01 06:11:30 +00:00
parent 8916922c6d
commit 50634cb638
4 changed files with 307 additions and 193 deletions

View file

@ -1,3 +1,13 @@
2012-03-01 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSXMLDocument.m:
* Source/NSXMLNode.m:
* Source/NSXMLElement.m:
Cleanup to conform to coding standards/conventions.
Fix lots of functions to be local in scope.
Add comments about needing to implement correct object ownership
model.
2012-02-27 Doug Simons <doug.simons@testplant.com> 2012-02-27 Doug Simons <doug.simons@testplant.com>
* Source/NSXMLNode.m: Fix a crashing bug after an invalid xpath * Source/NSXMLNode.m: Fix a crashing bug after an invalid xpath

View file

@ -43,8 +43,6 @@ GS_PRIVATE_INTERNAL(NSXMLDocument)
#if defined(HAVE_LIBXML) #if defined(HAVE_LIBXML)
extern void clearPrivatePointers(xmlNodePtr aNode);
// Private methods to manage libxml pointers... // Private methods to manage libxml pointers...
@interface NSXMLNode (Private) @interface NSXMLNode (Private)
- (void *) _node; - (void *) _node;

View file

@ -31,7 +31,6 @@ GS_PRIVATE_INTERNAL(NSXMLElement)
#if defined(HAVE_LIBXML) #if defined(HAVE_LIBXML)
extern void clearPrivatePointers(xmlNodePtr aNode);
// Private methods to manage libxml pointers... // Private methods to manage libxml pointers...
@interface NSXMLNode (Private) @interface NSXMLNode (Private)
@ -167,35 +166,35 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
xmlAttrPtr attr = (xmlAttrPtr)[attribute _node]; xmlAttrPtr attr = (xmlAttrPtr)[attribute _node];
xmlAttrPtr oldAttr = xmlHasProp(node, attr->name); xmlAttrPtr oldAttr = xmlHasProp(node, attr->name);
if (nil != [attribute parent]) if (nil != [attribute parent])
{ {
[NSException raise: @"NSInvalidArgumentException" [NSException raise: @"NSInvalidArgumentException"
format: @"Tried to add attribute to multiple parents."]; format: @"Tried to add attribute to multiple parents."];
} }
if (NULL != oldAttr) if (NULL != oldAttr)
{ {
/* /*
* As per Cocoa documentation, we only add the attribute if it's not * As per Cocoa documentation, we only add the attribute if it's not
* already set. xmlHasProp() also looks at the DTD for default attributes * already set. xmlHasProp() also looks at the DTD for default attributes
* and we need to make sure that we only bail out here on #FIXED * and we need to make sure that we only bail out here on #FIXED
* attributes. * attributes.
*/ */
// Do not replace plain attributes. // Do not replace plain attributes.
if (XML_ATTRIBUTE_NODE == oldAttr->type) if (XML_ATTRIBUTE_NODE == oldAttr->type)
{ {
return; return;
} }
else if (XML_ATTRIBUTE_DECL == oldAttr->type) else if (XML_ATTRIBUTE_DECL == oldAttr->type)
{ {
// If the attribute is from a DTD, do not replace it if it's #FIXED // If the attribute is from a DTD, do not replace it if it's #FIXED
xmlAttributePtr attrDecl = (xmlAttributePtr)oldAttr; xmlAttributePtr attrDecl = (xmlAttributePtr)oldAttr;
if (XML_ATTRIBUTE_FIXED == attrDecl->def) if (XML_ATTRIBUTE_FIXED == attrDecl->def)
{ {
return; return;
} }
} }
} }
xmlAddChild(node, (xmlNodePtr)attr); xmlAddChild(node, (xmlNodePtr)attr);
[self _addSubNode:attribute]; [self _addSubNode:attribute];
} }
@ -206,10 +205,11 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
xmlAttrPtr attr = xmlHasProp(node, (xmlChar *)[name UTF8String]); xmlAttrPtr attr = xmlHasProp(node, (xmlChar *)[name UTF8String]);
xmlAttrPtr newAttr = NULL; xmlAttrPtr newAttr = NULL;
NSXMLNode *attrNode = nil; NSXMLNode *attrNode = nil;
if (NULL == attr) if (NULL == attr)
{ {
return; return;
} }
// We need a copy of the node because xmlRemoveProp() frees attr: // We need a copy of the node because xmlRemoveProp() frees attr:
newAttr = xmlCopyProp(NULL, attr); newAttr = xmlCopyProp(NULL, attr);
@ -217,15 +217,15 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
// This is supposed to return failure for DTD defined attributes // This is supposed to return failure for DTD defined attributes
if (0 == xmlRemoveProp(attr)) if (0 == xmlRemoveProp(attr))
{ {
[attrNode _setNode: newAttr]; [attrNode _setNode: newAttr];
[self _removeSubNode: attrNode]; [self _removeSubNode: attrNode];
} }
else else
{ {
// In this case we throw away our copy again. // In this case we throw away our copy again.
xmlFreeProp(newAttr); xmlFreeProp(newAttr);
} }
} }
- (void) setAttributes: (NSArray*)attributes - (void) setAttributes: (NSArray*)attributes
@ -261,12 +261,14 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSArray*) attributes - (NSArray*) attributes
{ {
NSMutableArray *attributes = [NSMutableArray array]; NSMutableArray *attributes = [NSMutableArray array];
xmlNodePtr node = MY_NODE; xmlNodePtr node = MY_NODE;
struct _xmlAttr * attributeNode = node->properties; struct _xmlAttr *attributeNode = node->properties;
while (attributeNode) while (attributeNode)
{ {
NSXMLNode *attribute = [NSXMLNode _objectForNode:(xmlNodePtr)attributeNode]; NSXMLNode *attribute;
attribute = [NSXMLNode _objectForNode:(xmlNodePtr)attributeNode];
[attributes addObject:attribute]; [attributes addObject:attribute];
attributeNode = attributeNode->next; attributeNode = attributeNode->next;
} }
@ -275,13 +277,14 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
- (NSXMLNode*) attributeForName: (NSString*)name - (NSXMLNode*) attributeForName: (NSString*)name
{ {
NSXMLNode *result = nil; NSXMLNode *result = nil;
xmlChar *xmlName = xmlCharStrdup([name UTF8String]); xmlChar *xmlName = xmlCharStrdup([name UTF8String]);
xmlAttrPtr attributeNode = xmlHasProp(MY_NODE, xmlName); xmlAttrPtr attributeNode = xmlHasProp(MY_NODE, xmlName);
if (NULL != attributeNode) if (NULL != attributeNode)
{ {
result = [NSXMLNode _objectForNode:(xmlNodePtr)attributeNode]; result = [NSXMLNode _objectForNode:(xmlNodePtr)attributeNode];
} }
free(xmlName); // Free the name string since it's no longer needed. free(xmlName); // Free the name string since it's no longer needed.
xmlName = NULL; xmlName = NULL;
return result; // [internal->attributes objectForKey: name]; return result; // [internal->attributes objectForKey: name];
@ -490,7 +493,8 @@ extern void clearPrivatePointers(xmlNodePtr aNode);
[self removeChildAtIndex: index + 1]; [self removeChildAtIndex: index + 1];
} }
static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *nodesToDelete) static void
joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *nodesToDelete)
{ {
NSXMLNode *objA = (nodeA->_private), *objB = (nodeB->_private); NSXMLNode *objA = (nodeA->_private), *objB = (nodeB->_private);
@ -500,7 +504,10 @@ static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *no
{ {
if (objB != nil) // objB is now invalid if (objB != nil) // objB is now invalid
{ {
[objB _invalidate]; // set it to be invalid and make sure it's not pointing to a freed node /* set it to be invalid and make sure it's not
* pointing to a freed node
*/
[objB _invalidate];
[nodesToDelete addObject:objB]; [nodesToDelete addObject:objB];
} }
} }
@ -515,29 +522,40 @@ static void joinTextNodes(xmlNodePtr nodeA, xmlNodePtr nodeB, NSMutableArray *no
NSEnumerator *subEnum = [internal->subNodes objectEnumerator]; NSEnumerator *subEnum = [internal->subNodes objectEnumerator];
NSXMLNode *subNode = nil; NSXMLNode *subNode = nil;
NSMutableArray *nodesToDelete = [NSMutableArray array]; NSMutableArray *nodesToDelete = [NSMutableArray array];
while ((subNode = [subEnum nextObject])) while ((subNode = [subEnum nextObject]))
{ {
xmlNodePtr node = [subNode _node]; xmlNodePtr node = [subNode _node];
xmlNodePtr prev = node->prev; xmlNodePtr prev = node->prev;
xmlNodePtr next = node->next; xmlNodePtr next = node->next;
if (node->type == XML_ELEMENT_NODE) if (node->type == XML_ELEMENT_NODE)
[(NSXMLElement *)subNode normalizeAdjacentTextNodesPreservingCDATA:preserve]; {
else if (node->type == XML_TEXT_NODE || (node->type == XML_CDATA_SECTION_NODE && !preserve)) [(NSXMLElement *)subNode
normalizeAdjacentTextNodesPreservingCDATA:preserve];
}
else if (node->type == XML_TEXT_NODE
|| (node->type == XML_CDATA_SECTION_NODE && !preserve))
{ {
if (next && (next->type == XML_TEXT_NODE if (next && (next->type == XML_TEXT_NODE
|| (next->type == XML_CDATA_SECTION_NODE && !preserve))) || (next->type == XML_CDATA_SECTION_NODE && !preserve)))
{ {
//combine node & node->next //combine node & node->next
joinTextNodes(node, node->next, nodesToDelete); joinTextNodes(node, node->next, nodesToDelete);
} }
if (prev && (prev->type == XML_TEXT_NODE if (prev && (prev->type == XML_TEXT_NODE
|| (prev->type == XML_CDATA_SECTION_NODE && !preserve))) || (prev->type == XML_CDATA_SECTION_NODE && !preserve)))
{ {
//combine node->prev & node /* combine node->prev & node
// join the text of both nodes * join the text of both nodes
// assign the joined text to the earlier of the two nodes that has an ObjC object * assign the joined text to the earlier of the two
// unlink the other node * nodes that has an ObjC object
// delete the other node's object (maybe add it to a list of nodes to delete when we're done? -- or just set its node to null, and then remove it from our subNodes when we're done iterating it) (or maybe we need to turn it into an NSInvalidNode too??) * unlink the other node
* delete the other node's object (maybe add it to a
* list of nodes to delete when we're done? --
* or just set its node to null, and then remove it
* from our subNodes when we're done iterating it)
* (or maybe we need to turn it into an NSInvalidNode too??)
*/
joinTextNodes(node->prev, node, nodesToDelete); joinTextNodes(node->prev, node, nodesToDelete);
} }

View file

@ -31,7 +31,8 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
#if defined(HAVE_LIBXML) #if defined(HAVE_LIBXML)
int countAttributes(xmlNodePtr node) static int
countAttributes(xmlNodePtr node)
{ {
int count = 0; int count = 0;
xmlAttrPtr attr = node->properties; xmlAttrPtr attr = node->properties;
@ -45,14 +46,17 @@ int countAttributes(xmlNodePtr node)
return count; return count;
} }
BOOL isEqualAttr(const xmlAttrPtr attrA, const xmlAttrPtr attrB) static BOOL
isEqualAttr(const xmlAttrPtr attrA, const xmlAttrPtr attrB)
{ {
xmlChar* contentA; xmlChar *contentA;
xmlChar* contentB; xmlChar *contentB;
const xmlChar* nameA; const xmlChar *nameA;
const xmlChar* nameB; const xmlChar *nameB;
// what has to be the same for two attributes to be equal -- just their values?? /* what has to be the same for two attributes to be equal --
* just their values??
*/
if (attrB == attrA) if (attrB == attrA)
{ {
return YES; return YES;
@ -86,7 +90,8 @@ BOOL isEqualAttr(const xmlAttrPtr attrA, const xmlAttrPtr attrB)
return NO; return NO;
} }
xmlAttrPtr findAttrWithName(xmlNodePtr node, const xmlChar* targetName) static xmlAttrPtr
findAttrWithName(xmlNodePtr node, const xmlChar* targetName)
{ {
xmlAttrPtr attr = node->properties; xmlAttrPtr attr = node->properties;
@ -100,7 +105,8 @@ xmlAttrPtr findAttrWithName(xmlNodePtr node, const xmlChar* targetName)
} }
BOOL isEqualAttributes(xmlNodePtr nodeA, xmlNodePtr nodeB) static BOOL
isEqualAttributes(xmlNodePtr nodeA, xmlNodePtr nodeB)
{ {
xmlAttrPtr attrA = NULL; xmlAttrPtr attrA = NULL;
@ -121,7 +127,8 @@ BOOL isEqualAttributes(xmlNodePtr nodeA, xmlNodePtr nodeB)
return YES; return YES;
} }
BOOL isEqualNode(xmlNodePtr nodeA, xmlNodePtr nodeB) static BOOL
isEqualNode(xmlNodePtr nodeA, xmlNodePtr nodeB)
{ {
if (nodeA == nodeB) if (nodeA == nodeB)
return YES; return YES;
@ -158,7 +165,8 @@ BOOL isEqualNode(xmlNodePtr nodeA, xmlNodePtr nodeB)
return YES; return YES;
} }
BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB) static BOOL
isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
{ {
xmlNodePtr childA; xmlNodePtr childA;
xmlNodePtr childB; xmlNodePtr childB;
@ -239,40 +247,42 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
switch (type) switch (type)
{ {
case XML_DOCUMENT_NODE: case XML_DOCUMENT_NODE:
cls = [NSXMLDocument class]; cls = [NSXMLDocument class];
kind = NSXMLDocumentKind; kind = NSXMLDocumentKind;
break; break;
case XML_ELEMENT_NODE: case XML_ELEMENT_NODE:
cls = [NSXMLElement class]; cls = [NSXMLElement class];
kind = NSXMLElementKind; kind = NSXMLElementKind;
break; break;
case XML_TEXT_NODE: case XML_TEXT_NODE:
cls = [NSXMLNode class]; cls = [NSXMLNode class];
kind = NSXMLTextKind; kind = NSXMLTextKind;
break; break;
case XML_PI_NODE: case XML_PI_NODE:
cls = [NSXMLNode class]; cls = [NSXMLNode class];
kind = NSXMLProcessingInstructionKind; kind = NSXMLProcessingInstructionKind;
break; break;
case XML_COMMENT_NODE: case XML_COMMENT_NODE:
cls = [NSXMLNode class]; cls = [NSXMLNode class];
kind = NSXMLCommentKind; kind = NSXMLCommentKind;
break; break;
case XML_ATTRIBUTE_NODE: case XML_ATTRIBUTE_NODE:
cls = [NSXMLNode class]; cls = [NSXMLNode class];
kind = NSXMLAttributeKind; kind = NSXMLAttributeKind;
break; break;
default: default:
NSLog(@"ERROR: _objectForNode: called with a node of type %d", type); NSLog(@"ERROR: _objectForNode: called with a node of type %d",
return nil; type);
break; return nil;
break;
} }
if ((node->doc != NULL) && ((xmlNodePtr)(node->doc) != node)) if ((node->doc != NULL) && ((xmlNodePtr)(node->doc) != node))
{ {
NSXMLDocument *doc; NSXMLDocument *doc;
doc = (NSXMLDocument*)[self _objectForNode: (xmlNodePtr)node->doc]; doc = (NSXMLDocument*)[self
_objectForNode: (xmlNodePtr)node->doc];
if (doc != nil) if (doc != nil)
{ {
cls = [[doc class] replacementClassForClass: cls]; cls = [[doc class] replacementClassForClass: cls];
@ -292,6 +302,24 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
return result; return result;
} }
/* FIXME ... the whole following section working with externalRetains
* depends on unsafe assumptions about the functioning of the (deprecated)
* -retainCount method).
* There's no documented policy on object ownership ... so it's not clear
* what this code *should* do.
* The actual OSX policy should be determined and documented, then we
* need to produce code which implements the same behavior in a manner
* consistent with ARC and CR as well as old fashioned retain counts
* (though we may not want to replicate OSX bugs).
* It seems to me that there should be no need for the externalRetains
* counter and definitely no overriding of -retain or -release or use
* of -retainCount
* A naive (simple/obvious) model would be to say that parents own their
* children, so when the root is deallocated, all the children get detached
* and released. In this case retaining a node within a document would cause
* that node and its children to persist when the document was released.
* But maybe Apple did something different?
*/
- (int) _externalRetains - (int) _externalRetains
{ {
return internal->externalRetains; return internal->externalRetains;
@ -299,10 +327,12 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
- (int) verifyExternalRetains - (int) verifyExternalRetains
{ {
int extraRetains = ([self retainCount] > 1 ? 1 : 0); // start with 1 or 0 for ourself // start with 1 or 0 for ourself
int extraRetains = ([self retainCount] > 1 ? 1 : 0);
int index; int index;
for (index = 0; index < [internal->subNodes count]; index++) for (index = 0; index < [internal->subNodes count]; index++)
extraRetains += [[internal->subNodes objectAtIndex: index] _externalRetains]; extraRetains
+= [[internal->subNodes objectAtIndex: index] _externalRetains];
return extraRetains; return extraRetains;
} }
@ -311,27 +341,37 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
xmlNodePtr pnode = (MY_NODE ? MY_NODE->parent : NULL); xmlNodePtr pnode = (MY_NODE ? MY_NODE->parent : NULL);
NSXMLNode *parent = (NSXMLNode *)(pnode ? pnode->_private : nil); NSXMLNode *parent = (NSXMLNode *)(pnode ? pnode->_private : nil);
int oldCount = internal->externalRetains; int oldCount = internal->externalRetains;
int extraRetains = ([self retainCount] > 1 ? 1 : 0); // start with 1 or 0 for ourself // start with 1 or 0 for ourself
int extraRetains = ([self retainCount] > 1 ? 1 : 0);
int index; int index;
for (index = 0; index < [internal->subNodes count]; index++) for (index = 0; index < [internal->subNodes count]; index++)
extraRetains += [[internal->subNodes objectAtIndex: index] _externalRetains]; extraRetains
+= [[internal->subNodes objectAtIndex: index] _externalRetains];
internal->externalRetains = extraRetains; internal->externalRetains = extraRetains;
if (extraRetains != oldCount) if (extraRetains != oldCount)
{ {
if (parent) if (parent)
[parent _updateExternalRetains]; // tell our parent (if any) since our count has changed {
// tell our parent (if any) since our count has changed
[parent _updateExternalRetains];
}
else else
{ // we're the root node of this tree, so retain or release ourself as needed {
/* we're the root node of this tree, so retain or
* release ourself as needed
*/
if (oldCount == 0 && extraRetains > 0) if (oldCount == 0 && extraRetains > 0)
{ {
[super retain]; [super retain];
internal->retainedSelf++; internal->retainedSelf++;
//NSLog(@"RETAINED SELF %@ (%d)", self, internal->retainedSelf); NSDebugLLog(@"NSXMLNode", @"RETAINED SELF %@ (%d)",
self, internal->retainedSelf);
} }
else if (oldCount > 0 && extraRetains == 0 && internal->retainedSelf) else if (oldCount > 0 && extraRetains == 0 && internal->retainedSelf)
{ {
internal->retainedSelf--; internal->retainedSelf--;
//NSLog(@"RELEASED SELF %@ (%d)", self, internal->retainedSelf); NSDebugLLog(@"NSXMLNode", @"RELEASED SELF %@ (%d)",
self, internal->retainedSelf);
[super release]; [super release];
} }
} }
@ -344,12 +384,16 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
{ {
[super retain]; [super retain];
internal->retainedSelf++; internal->retainedSelf++;
//NSLog(@"RETAINED SELF AFTER STATUS CHANGED %@ (%d)", self, internal->retainedSelf); NSDebugLLog(@"NSXMLNode",
@"RETAINED SELF AFTER STATUS CHANGED %@ (%d)",
self, internal->retainedSelf);
} }
else if (extraRetains == 0 && internal->retainedSelf > 0) else if (extraRetains == 0 && internal->retainedSelf > 0)
{ {
internal->retainedSelf--; internal->retainedSelf--;
//NSLog(@"RELEASED SELF AFTER STATUS CHANGED %@ (%d)", self, internal->retainedSelf); NSDebugLLog(@"NSXMLNode",
@"RELEASED SELF AFTER STATUS CHANGED %@ (%d)",
self, internal->retainedSelf);
[super release]; [super release];
} }
} }
@ -358,43 +402,66 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
- (void) _passExternalRetainsTo: (NSXMLNode *)parent - (void) _passExternalRetainsTo: (NSXMLNode *)parent
{ {
// this object just became a subNode, so pass knowledge of external retains up the line /* this object just became a subNode, so pass knowledge of
* external retains up the line
*/
if (internal->externalRetains > 0) if (internal->externalRetains > 0)
{ {
//NSLog(@"_passExternalRetainsTo: %@ (%d,%d) from %@ Start: (%d,%d)", parent, [parent _externalRetains], [parent verifyExternalRetains], self, internal->externalRetains, [self verifyExternalRetains]); NSDebugLLog(@"NSXMLNode",
@"_passExternalRetainsTo: %@ (%d,%d) from %@ Start: (%d,%d)",
parent, [parent _externalRetains], [parent verifyExternalRetains],
self, internal->externalRetains, [self verifyExternalRetains]);
// if ([self retainCount] == 2) // if ([self retainCount] == 2)
// { // {
// internal->externalRetains--; // internal->externalRetains--;
//NSLog(@"RELEASING TRICKY EXTRA RETAIN WHILE ADDING TO PARENT in %@ now: %d", self, internal->externalRetains); // NSDebugLLog(@"NSXMLNode",
// @"RELEASING TRICKY EXTRA RETAIN WHILE ADDING TO PARENT "
// @"in %@ now: %d", self, internal->externalRetains);
// } // }
//[self _updateExternalRetains]; //[self _updateExternalRetains];
if (internal->retainedSelf) if (internal->retainedSelf)
{ {
[super release]; // we're no longer the root of our branch, so stop retaining ourself // we're no longer the root of our branch, so stop retaining ourself
internal->retainedSelf--; [super release];
//NSLog(@"RELEASED SELF %@ (%d) in _passExternal...", self, internal->retainedSelf); internal->retainedSelf--;
NSDebugLLog(@"NSXMLNode",
@"RELEASED SELF %@ (%d) in _passExternal...",
self, internal->retainedSelf);
} }
[parent _updateExternalRetains]; [parent _updateExternalRetains];
//NSLog(@"DID _passExternalRetainsTo: %@ (%d,%d) from %@ End: (%d,%d)", parent, [parent _externalRetains], [parent verifyExternalRetains], self, internal->externalRetains, [self verifyExternalRetains]); NSDebugLLog(@"NSXMLNode",
@"DID _passExternalRetainsTo: %@ (%d,%d) from %@ End: (%d,%d)",
parent, [parent _externalRetains], [parent verifyExternalRetains],
self, internal->externalRetains, [self verifyExternalRetains]);
} }
} }
- (void) _removeExternalRetainsFrom: (NSXMLNode *)parent - (void) _removeExternalRetainsFrom: (NSXMLNode *)parent
{ {
// this object is no longer a subNode, so pass removal of external retains up the line /* this object is no longer a subNode, so pass removal of
* external retains up the line
*/
if (internal->externalRetains > 0) if (internal->externalRetains > 0)
{ {
//NSLog(@"_removeExternalRetainsTo: %@ from %@ Start: %d", parent, self, internal->externalRetains); NSDebugLLog(@"NSXMLNode",
/// [parent releaseExternalRetain: internal->externalRetains]; @"_removeExternalRetainsTo: %@ from %@ Start: %d",
if ([self retainCount] == 1) parent, self, internal->externalRetains);
{ // [parent releaseExternalRetain: internal->externalRetains];
internal->externalRetains++; if ([self retainCount] == 1)
//NSLog(@"ADDED TRICKY EXTRA COUNT WHILE REMOVING FROM PARENT in %@ now: %d subNodes(low): %d", self, internal->externalRetains, [self verifyExternalRetains]); {
} internal->externalRetains++;
NSDebugLLog(@"NSXMLNode",
@"ADDED TRICKY EXTRA COUNT WHILE REMOVING FROM PARENT in %@ "
@"now: %d subNodes(low): %d", self, internal->externalRetains,
[self verifyExternalRetains]);
}
[super retain]; // becoming detached, so retain ourself as the new root of our branch // becoming detached, so retain ourself as the new root of our branch
[super retain];
internal->retainedSelf++; internal->retainedSelf++;
//NSLog(@"RETAINED SELF %@ (%d) in _removeExternal...", self, internal->retainedSelf); NSDebugLLog(@"NSXMLNode",
@"RETAINED SELF %@ (%d) in _removeExternal...",
self, internal->retainedSelf);
[parent _updateExternalRetains]; [parent _updateExternalRetains];
} }
} }
@ -412,7 +479,8 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
- (void) _removeSubNode: (NSXMLNode *)subNode - (void) _removeSubNode: (NSXMLNode *)subNode
{ {
[subNode retain]; // retain temporarily so we can safely remove from our subNodes list first // retain temporarily so we can safely remove from our subNodes list first
[subNode retain];
[internal->subNodes removeObjectIdenticalTo: subNode]; [internal->subNodes removeObjectIdenticalTo: subNode];
[subNode _removeExternalRetainsFrom: self]; [subNode _removeExternalRetainsFrom: self];
[subNode release]; // release temporary hold [subNode release]; // release temporary hold
@ -439,15 +507,16 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
NSUInteger count = 0; NSUInteger count = 0;
xmlNodePtr node = (xmlNodePtr)(internal->node); xmlNodePtr node = (xmlNodePtr)(internal->node);
xmlNodePtr children = node->children; xmlNodePtr children = node->children;
if (!children) if (!children)
return NULL; // the Cocoa docs say it returns nil if there are no children return NULL; // the Cocoa docs say it returns nil if there are no children
for (children = node->children; children != NULL && count != index; children = children->next) while (children != NULL && count++ < index)
{ {
count++; children = children->next;
} }
if (count != index) if (count < index)
[NSException raise: NSRangeException format: @"child index too large"]; [NSException raise: NSRangeException format: @"child index too large"];
return children; return children;
@ -455,7 +524,9 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
- (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index - (void) _insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{ {
// this private method provides the common insertion implementation used by NSXMLElement and NSXMLDocument /* this private method provides the common insertion
* implementation used by NSXMLElement and NSXMLDocument
*/
// Get all of the nodes... // Get all of the nodes...
xmlNodePtr parentNode = MY_NODE; // we are the parent xmlNodePtr parentNode = MY_NODE; // we are the parent
@ -485,7 +556,9 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
} }
else else
{ {
// here we avoid merging adjacent text nodes by linking the new node in "by hand" /* here we avoid merging adjacent text nodes by linking
* the new node in "by hand"
*/
childNode->parent = parentNode; childNode->parent = parentNode;
if (curNode) if (curNode)
{ {
@ -500,7 +573,9 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
} }
else else
{ {
// in this case, this is the new "first child", so update our parent to point to it /* in this case, this is the new "first child",
* so update our parent to point to it
*/
parentNode->children = childNode; parentNode->children = childNode;
} }
} }
@ -534,7 +609,8 @@ BOOL isEqualTree(xmlNodePtr nodeA, xmlNodePtr nodeB)
@end @end
void clearPrivatePointers(xmlNodePtr aNode) static void
clearPrivatePointers(xmlNodePtr aNode)
{ {
if (!aNode) if (!aNode)
return; return;
@ -545,8 +621,8 @@ void clearPrivatePointers(xmlNodePtr aNode)
clearPrivatePointers((xmlNodePtr)(aNode->properties)); clearPrivatePointers((xmlNodePtr)(aNode->properties));
} }
int register_namespaces(xmlXPathContextPtr xpathCtx, static int
const xmlChar* nsList) register_namespaces(xmlXPathContextPtr xpathCtx, const xmlChar* nsList)
{ {
xmlChar* nsListDup; xmlChar* nsListDup;
xmlChar* prefix; xmlChar* prefix;
@ -592,8 +668,8 @@ int register_namespaces(xmlXPathContextPtr xpathCtx,
/* do register namespace */ /* do register namespace */
if (xmlXPathRegisterNs(xpathCtx, prefix, href) != 0) if (xmlXPathRegisterNs(xpathCtx, prefix, href) != 0)
{ {
NSLog(@"Error: unable to register NS with prefix=\"%s\" and href=\"%s\"", NSLog(@"Error: unable to register NS with prefix=\"%s\""
prefix, href); @" and href=\"%s\"", prefix, href);
xmlFree(nsListDup); xmlFree(nsListDup);
return -1; return -1;
} }
@ -603,9 +679,8 @@ int register_namespaces(xmlXPathContextPtr xpathCtx,
return 0; return 0;
} }
NSArray *execute_xpath(NSXMLNode *xmlNode, static NSArray *
NSString *xpath_exp, execute_xpath(NSXMLNode *xmlNode, NSString *xpath_exp, NSString *nmspaces)
NSString *nmspaces)
{ {
xmlNodePtr node = [xmlNode _node]; xmlNodePtr node = [xmlNode _node];
xmlDocPtr doc = node->doc; xmlDocPtr doc = node->doc;
@ -815,27 +890,27 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
if ([name isEqualToString: @"xml"]) if ([name isEqualToString: @"xml"])
{ {
return [self namespaceWithName: @"xml" return [self namespaceWithName: @"xml"
stringValue: @"http: //www.w3.org/XML/1998/namespace"]; stringValue: @"http: //www.w3.org/XML/1998/namespace"];
} }
if ([name isEqualToString: @"xs"]) if ([name isEqualToString: @"xs"])
{ {
return [self namespaceWithName: @"xs" return [self namespaceWithName: @"xs"
stringValue: @"http: //www.w3.org/2001/XMLSchema"]; stringValue: @"http: //www.w3.org/2001/XMLSchema"];
} }
if ([name isEqualToString: @"xsi"]) if ([name isEqualToString: @"xsi"])
{ {
return [self namespaceWithName: @"xsi" return [self namespaceWithName: @"xsi"
stringValue: @"http: //www.w3.org/2001/XMLSchema-instance"]; stringValue: @"http: //www.w3.org/2001/XMLSchema-instance"];
} }
if ([name isEqualToString: @"fn"]) if ([name isEqualToString: @"fn"])
{ {
return [self namespaceWithName: @"fn" return [self namespaceWithName: @"fn"
stringValue: @"http: //www.w3.org/2003/11/xpath-functions"]; stringValue: @"http: //www.w3.org/2003/11/xpath-functions"];
} }
if ([name isEqualToString: @"local"]) if ([name isEqualToString: @"local"])
{ {
return [self namespaceWithName: @"local" return [self namespaceWithName: @"local"
stringValue: @"http: //www.w3.org/2003/11/xpath-local-functions"]; stringValue: @"http: //www.w3.org/2003/11/xpath-local-functions"];
} }
return nil; return nil;
@ -956,10 +1031,12 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
- (NSString*) description - (NSString*) description
{ {
return [NSString stringWithFormat:@"<%@ %@ %d>%@\n", return [NSString stringWithFormat:@"<%@ %@ %d>%@\n",
NSStringFromClass([self class]), NSStringFromClass([self class]),
[self name], [self kind], [self stringValue]]; [self name], [self kind], [self stringValue]];
} }
/* FIXME ... this method should be deleted!
*/
- (id) retain - (id) retain
{ {
[super retain]; // do this first [super retain]; // do this first
@ -970,6 +1047,8 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
return self; return self;
} }
/* FIXME ... this method should be deleted!
*/
- (void) release - (void) release
{ {
if ([self retainCount] == 2) if ([self retainCount] == 2)
@ -1009,28 +1088,36 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
if (node) if (node)
{ {
xmlNodePtr parentNode = node->parent; xmlNodePtr parentNode = node->parent;
NSXMLNode *parent = (parentNode ? parentNode->_private : nil); // get our parent object if it exists NSXMLNode *parent = (parentNode ? parentNode->_private : nil);
xmlUnlinkNode(node); // separate our node from its parent and siblings xmlUnlinkNode(node); // separate our node from its parent and siblings
if (parent) if (parent)
{ {
int extraRetains = 0; int extraRetains = 0;
// transfer extra retains of this branch from our parent to ourself // transfer extra retains of this branch from our parent to ourself
extraRetains = internal->externalRetains; //[self verifyExternalRetains]; extraRetains = internal->externalRetains;
//[self verifyExternalRetains];
if (extraRetains) if (extraRetains)
{ {
/// [parent releaseExternalRetain: extraRetains]; /// [parent releaseExternalRetain: extraRetains];
if ([self retainCount] == 1) if ([self retainCount] == 1)
{ {
internal->externalRetains++; internal->externalRetains++;
//NSLog(@"ADDED TRICKY EXTRA COUNT WHILE DETACHING in %@ now: %d subNodes(low): %d", self, internal->externalRetains, [self verifyExternalRetains]); NSDebugLLog(@"NSXMLNode",
} @"ADDED TRICKY EXTRA COUNT WHILE DETACHING in %@ now: "
@"%d subNodes(low): %d", self, internal->externalRetains,
[self verifyExternalRetains]);
}
[super retain]; //[self recordExternalRetain: extraRetains]; [super retain]; //[self recordExternalRetain: extraRetains];
internal->retainedSelf++; internal->retainedSelf++;
//NSLog(@"RETAINED SELF %@ (%d) in detach", self, internal->retainedSelf); NSDebugLLog(@"NSXMLNode", @"RETAINED SELF %@ (%d) in detach",
self, internal->retainedSelf);
} }
[parent _removeSubNode: self]; [parent _removeSubNode: self];
NSDebugLLog(@"NSXMLNode",
@"DETACHED %@ from %@ and transferred extra retains: %d",
self, parent, extraRetains);
} }
//NSLog(@"DETACHED %@ from %@ and transferred extra retains: %d", self, parent, extraRetains);
} }
} }
@ -1118,8 +1205,8 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
/* /*
* Check whether we are already initializing an instance of the given * Check whether we are already initializing an instance of the given
* subclass. If we are not, release ourselves and allocate a subclass instance * subclass. If we are not, release ourselves and allocate a subclass
* instead. * instance instead.
*/ */
if (NO == [self isKindOfClass: theSubclass]) if (NO == [self isKindOfClass: theSubclass])
{ {
@ -1130,47 +1217,47 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
switch (kind) switch (kind)
{ {
case NSXMLDocumentKind: case NSXMLDocumentKind:
node = xmlNewDoc((xmlChar *)"1.0"); node = xmlNewDoc((xmlChar *)"1.0");
break; break;
case NSXMLInvalidKind:
case NSXMLElementKind:
node = xmlNewNode(NULL,(xmlChar *)"");
break;
case NSXMLInvalidKind: case NSXMLDTDKind:
case NSXMLElementKind: node = xmlNewDtd(NULL, (xmlChar *)"", (xmlChar *)"",(xmlChar *)"");
node = xmlNewNode(NULL,(xmlChar *)""); break;
break;
case NSXMLEntityDeclarationKind:
case NSXMLDTDKind: case NSXMLElementDeclarationKind:
node = xmlNewDtd(NULL, (xmlChar *)"", (xmlChar *)"",(xmlChar *)""); case NSXMLNotationDeclarationKind:
break; node = xmlNewNode(NULL, (xmlChar *)"");
break;
case NSXMLEntityDeclarationKind:
case NSXMLElementDeclarationKind:
case NSXMLNotationDeclarationKind:
node = xmlNewNode(NULL, (xmlChar *)"");
break;
case NSXMLProcessingInstructionKind: case NSXMLProcessingInstructionKind:
node = xmlNewPI((xmlChar *)"", (xmlChar *)""); node = xmlNewPI((xmlChar *)"", (xmlChar *)"");
break; break;
case NSXMLCommentKind: case NSXMLCommentKind:
node = xmlNewComment((xmlChar *)""); node = xmlNewComment((xmlChar *)"");
break; break;
case NSXMLTextKind: case NSXMLTextKind:
node = xmlNewText((xmlChar *)""); node = xmlNewText((xmlChar *)"");
break; break;
case NSXMLNamespaceKind: case NSXMLNamespaceKind:
node = xmlNewNs(NULL,(xmlChar *)"",(xmlChar *)""); node = xmlNewNs(NULL,(xmlChar *)"",(xmlChar *)"");
break; break;
case NSXMLAttributeKind: case NSXMLAttributeKind:
node = xmlNewProp(NULL,(xmlChar *)"",(xmlChar *)""); node = xmlNewProp(NULL,(xmlChar *)"",(xmlChar *)"");
break; break;
default: default:
break; break;
} }
/* Create holder for internal instance variables if needed. /* Create holder for internal instance variables if needed.
@ -1316,7 +1403,8 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
- (NSXMLDocument*) rootDocument - (NSXMLDocument*) rootDocument
{ {
return (NSXMLDocument *)[NSXMLNode _objectForNode: (xmlNodePtr)(MY_NODE->doc)]; return
(NSXMLDocument *)[NSXMLNode _objectForNode: (xmlNodePtr)(MY_NODE->doc)];
} }
- (NSString*) stringValue - (NSString*) stringValue
@ -1326,8 +1414,8 @@ NSArray *execute_xpath(NSXMLNode *xmlNode,
NSString *result = nil; NSString *result = nil;
/* /*
if (node->type == XML_ATTRIBUTE_NODE || if (node->type == XML_ATTRIBUTE_NODE
node->type == XML_ELEMENT_NODE) || node->type == XML_ELEMENT_NODE)
{ {
node = node->children; node = node->children;
} }