Fix NSXML ABI breakage

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@34412 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2012-01-04 12:41:45 +00:00
parent 40f8c557c9
commit ded72b8e75
13 changed files with 384 additions and 228 deletions

View file

@ -1,3 +1,21 @@
2012-01-04 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSXMLDocument.h:
* Headers/Foundation/NSXMLNode.h:
* Headers/Foundation/NSXMLDTD.h:
* Headers/Foundation/NSXMLDTDNode.h:
* Headers/Foundation/NSXMLElement.h:
* Source/NSXMLDocument.m:
* Source/NSXMLPrivate.h:
* Source/NSXMLDTD.m:
* Source/GSInternal.h:
* Source/NSXMLNode.m:
* Source/NSXMLDTDNode.m:
* Source/NSXMLElement.m:
The last revert still left lot's of ABI breakage, but reverting much
further would lose a lot of work ... so here's an attempt to fix the
ABI breakage by re-hiding instance variables again.
2012-01-04 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSMDNSNetServices.m:

View file

@ -41,20 +41,15 @@ extern "C" {
*/
@interface NSXMLDTD : NSXMLNode
{
#if GS_EXPOSE(NSXMLDTD)
@private
//NSString *_name;
NSString *_publicID;
NSString *_systemID;
NSArray *_children;
BOOL _childrenHaveMutated;
BOOL _modified;
NSMutableDictionary *_entities;
NSMutableDictionary *_elements;
NSMutableDictionary *_notations;
NSMutableDictionary *_attributes;
NSString *_original;
#if GS_NONFRAGILE
# if defined(GS_NSXMLDTD_IVARS)
@public GS_NSXMLDTD_IVARS
# endif
#endif
/* The pointer to private additional data used to avoid breaking ABI
* when we don't have the non-fragile ABI available is inherited from
* NSXMLNode. See Source/GSInternal.h for details.
*/
}
/**

View file

@ -75,14 +75,15 @@ typedef NSUInteger NSXMLDTDNodeKind;
*/
@interface NSXMLDTDNode : NSXMLNode
{
#if GS_EXPOSE(NSXMLDTDNode)
@protected
NSXMLDTDNodeKind _DTDKind;
//NSString *_name;
NSString *_notationName;
NSString *_publicID;
NSString *_systemID;
#if GS_NONFRAGILE
# if defined(GS_NSXMLDTDNode_IVARS)
@public GS_NSXMLDTDNode_IVARS
# endif
#endif
/* The pointer to private additional data used to avoid breaking ABI
* when we don't have the non-fragile ABI available is inherited from
* NSXMLNode. See Source/GSInternal.h for details.
*/
}
/**

View file

@ -74,24 +74,15 @@ typedef NSUInteger NSXMLDocumentContentKind;
*/
@interface NSXMLDocument : NSXMLNode
{
#if GS_EXPOSE(NSXMLDocument)
@protected
NSString *_encoding;
NSString *_version;
NSXMLDTD *_docType;
NSArray *_children;
BOOL _childrenHaveMutated;
BOOL _standalone;
NSXMLElement *_rootElement;
NSString *_URI;
NSString *_MIMEType;
NSUInteger _fidelityMask;
NSXMLDocumentContentKind _contentKind;
@private
NSMutableArray *_elementStack;
NSData *_xmlData;
#if GS_NONFRAGILE
# if defined(GS_NSXMLDocument_IVARS)
@public GS_NSXMLDocument_IVARS
# endif
#endif
/* The pointer to private additional data used to avoid breaking ABI
* when we don't have the non-fragile ABI available is inherited from
* NSXMLNode. See Source/GSInternal.h for details.
*/
}
+ (Class) replacementClassForClass: (Class)cls;

View file

@ -39,14 +39,15 @@ extern "C" {
*/
@interface NSXMLElement : NSXMLNode
{
#if GS_EXPOSE(NSXMLElement)
@protected
NSMutableDictionary *_attributes;
NSMutableArray *_namespaces;
NSMutableArray *_children;
BOOL _childrenHaveMutated;
NSInteger _prefixIndex;
#if GS_NONFRAGILE
# if defined(GS_NSXMLElement_IVARS)
@public GS_NSXMLElement_IVARS
# endif
#endif
/* The pointer to private additional data used to avoid breaking ABI
* when we don't have the non-fragile ABI available is inherited from
* NSXMLNode. See Source/GSInternal.h for details.
*/
}
/**

View file

@ -80,17 +80,6 @@ typedef NSUInteger NSXMLNodeKind;
*/
@interface NSXMLNode : NSObject <NSCopying>
{
#if GS_EXPOSE(NSXMLNode)
@protected
void *_handle;
NSXMLNodeKind _kind;
NSXMLNode *_parent;
NSUInteger _index;
id _objectValue;
NSString *_stringValue;
NSString *_name;
NSString *_URI;
#endif
#if GS_NONFRAGILE
# if defined(GS_NSXMLNode_IVARS)
@public GS_NSXMLNode_IVARS
@ -100,8 +89,10 @@ typedef NSUInteger NSXMLNodeKind;
* when we don't have the non-fragile ABI available.
* Use this mechanism rather than changing the instance variable
* layout (see Source/GSInternal.h for details).
* In this case it's declared protected so that the NSXMLNode
* subclasses can share the same variables.
*/
@private id _internal GS_UNUSED_IVAR;
@protected id _internal GS_UNUSED_IVAR;
#endif
}

View file

@ -95,21 +95,26 @@ GS_##name##_IVARS; \
/* Create holder for internal ivars.
*/
#define GS_CREATE_INTERNAL(name) \
_internal = [name ## Internal new];
if (nil == _internal) { _internal = [name ## Internal new]; }
/* Destroy holder for internal ivars.
*/
#define GS_DESTROY_INTERNAL(name) \
if (nil != _internal) {[_internal release]; _internal = nil; }
if (nil != _internal) { [_internal release]; _internal = nil; }
/* Create a new copy of the current object's internal class and place
* it in the destination instance. This poduces a bitwise copy, and you
* it in the destination instance. This produces a bitwise copy, and you
* may wish to perform further action to deepen the copy after using this
* macro.
* Use this only where D is a new copy of the current instance.
*/
#define GS_COPY_INTERNAL(D,Z) (D)->_internal = NSCopyObject(_internal, 0, (Z));
/* Checks to see if internal instance variables exist ... use in -dealloc if
* there is any chance that the instance is being deallocated before they
* were created.
*/
#define GS_EXISTS_INTERNAL (nil == _internal ? NO : YES)
#undef internal
#define internal ((GSInternal*)_internal)
@ -129,6 +134,8 @@ if (nil != _internal) {[_internal release]; _internal = nil; }
#define GS_COPY_INTERNAL(D,Z)
#define GS_EXISTS_INTERNAL YES
/* Define constant to reference internal ivars.
*/
#undef internal

View file

@ -26,6 +26,10 @@
#import "NSXMLPrivate.h"
#define GSInternal NSXMLDTDInternal
#include "GSInternal.h"
GS_PRIVATE_INTERNAL(NSXMLDTD)
@implementation NSXMLDTD
+ (NSXMLDTDNode*) predefinedEntityDeclarationForName: (NSString*)name
@ -36,15 +40,16 @@
- (void) dealloc
{
[_name release];
[_publicID release];
[_systemID release];
[_children release];
[_entities release];
[_elements release];
[_notations release];
[_attributes release];
[_original release];
if (GS_EXISTS_INTERNAL)
{
[internal->publicID release];
[internal->systemID release];
[internal->entities release];
[internal->elements release];
[internal->notations release];
[internal->attributes release];
[internal->original release];
}
[super dealloc];
}
@ -93,10 +98,22 @@
return nil;
}
- (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
{
if (NSXMLDTDKind == kind)
{
/* Create holder for internal instance variables so that we'll have
* all our ivars available rather than just those of the superclass.
*/
GS_CREATE_INTERNAL(NSXMLDTD)
}
return [super initWithKind: kind options: theOptions];
}
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
[self notImplemented: _cmd];
_childrenHaveMutated = YES;
internal->childrenHaveMutated = YES;
}
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index
@ -112,7 +129,7 @@
- (NSXMLDTDNode*) notationDeclarationForName: (NSString*)name
{
NSXMLDTDNode *notation = [_notations objectForKey: name];
NSXMLDTDNode *notation = [internal->notations objectForKey: name];
if (notation == nil)
{
@ -123,11 +140,11 @@
- (NSString*) publicID
{
if (_publicID == nil)
if (internal->publicID == nil)
{
[self notImplemented: _cmd];
}
return _publicID;
return internal->publicID;
}
- (void) removeChildAtIndex: (NSUInteger)index
@ -148,22 +165,22 @@
- (void) setPublicID: (NSString*)publicID
{
[self notImplemented: _cmd];
_modified = YES;
internal->modified = YES;
}
- (void) setSystemID: (NSString*)systemID
{
[self notImplemented: _cmd];
_modified = YES;
internal->modified = YES;
}
- (NSString*) systemID
{
if (_systemID == nil)
if (internal->systemID == nil)
{
[self notImplemented: _cmd];
}
return _systemID;
return internal->systemID;
}
@end

View file

@ -26,20 +26,40 @@
#import "NSXMLPrivate.h"
#define GSInternal NSXMLDTDNodeInternal
#include "GSInternal.h"
GS_PRIVATE_INTERNAL(NSXMLDTDNode)
@implementation NSXMLDTDNode
- (void) dealloc
{
[_name release];
[_notationName release];
[_publicID release];
[_systemID release];
if (GS_EXISTS_INTERNAL)
{
[internal->notationName release];
[internal->publicID release];
[internal->systemID release];
}
[super dealloc];
}
- (NSXMLDTDNodeKind) DTDKind
{
return _DTDKind;
return internal->DTDKind;
}
- (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
{
if (NSXMLEntityDeclarationKind == kind
|| NSXMLElementDeclarationKind
|| NSXMLNotationDeclarationKind)
{
/* Create holder for internal instance variables so that we'll have
* all our ivars available rather than just those of the superclass.
*/
GS_CREATE_INTERNAL(NSXMLDTDNode)
}
return [super initWithKind: kind options: theOptions];
}
- (id) initWithXMLString: (NSString*)string
@ -50,7 +70,7 @@
- (BOOL) isExternal
{
if (_systemID != nil)
if (internal->systemID != nil)
{
// FIXME ... libxml integration?
return YES;
@ -60,53 +80,53 @@
- (NSString*) notationName
{
if (_notationName == nil)
if (internal->notationName == nil)
{
[self notImplemented: _cmd];
}
return _notationName;
return internal->notationName;
}
- (NSString*) publicID
{
if (_publicID == nil)
if (internal->publicID == nil)
{
[self notImplemented: _cmd];
}
return _publicID;
return internal->publicID;
}
- (void) setDTDKind: (NSXMLDTDNodeKind)kind
{
_DTDKind = kind;
internal->DTDKind = kind;
// FIXME ... libxml integration?
}
- (void) setNotationName: (NSString*)notationName
{
ASSIGNCOPY(_notationName, notationName);
ASSIGNCOPY(internal->notationName, notationName);
// FIXME ... libxml integration?
}
- (void) setPublicID: (NSString*)publicID
{
ASSIGNCOPY(_publicID, publicID);
ASSIGNCOPY(internal->publicID, publicID);
// FIXME ... libxml integration?
}
- (void) setSystemID: (NSString*)systemID
{
ASSIGNCOPY(_systemID, systemID);
ASSIGNCOPY(internal->systemID, systemID);
// FIXME ... libxml integration?
}
- (NSString*) systemID
{
if (_systemID == nil)
if (internal->systemID == nil)
{
[self notImplemented: _cmd];
}
return _systemID;
return internal->systemID;
}
@end

View file

@ -25,6 +25,11 @@
#import "common.h"
#import "NSXMLPrivate.h"
#define GSInternal NSXMLDocumentInternal
#include "GSInternal.h"
GS_PRIVATE_INTERNAL(NSXMLDocument)
#import <Foundation/NSXMLParser.h>
// Forward declaration of interface for NSXMLParserDelegate
@ -40,30 +45,31 @@
- (void) dealloc
{
RELEASE(_encoding);
RELEASE(_version);
RELEASE(_docType);
RELEASE(_children);
RELEASE(_URI);
RELEASE(_MIMEType);
RELEASE(_elementStack);
RELEASE(_xmlData);
if (GS_EXISTS_INTERNAL)
{
[internal->encoding release];
[internal->version release];
[internal->docType release];
[internal->MIMEType release];
[internal->elementStack release];
[internal->xmlData release];
}
[super dealloc];
}
- (NSString*) characterEncoding
{
return _encoding;
return internal->encoding;
}
- (NSXMLDocumentContentKind) documentContentKind
{
return _contentKind;
return internal->contentKind;
}
- (NSXMLDTD*) DTD
{
return _docType;
return internal->docType;
}
- (id) initWithContentsOfURL: (NSURL*)url
@ -84,15 +90,16 @@
options: (NSUInteger)mask
error: (NSError**)error
{
if ((self = [super init]) != nil)
GS_CREATE_INTERNAL(NSXMLDocument)
if ((self = [super initWithKind: NSXMLDocumentKind options: 0]) != nil)
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithData: data];
if (parser != nil)
{
_standalone = YES;
_children = [[NSMutableArray alloc] initWithCapacity: 10];
_elementStack = [[NSMutableArray alloc] initWithCapacity: 10];
ASSIGN(_xmlData, data);
internal->standalone = YES;
internal->elementStack = [[NSMutableArray alloc] initWithCapacity: 10];
ASSIGN(internal->xmlData, data);
[parser setDelegate: self];
[parser parse];
RELEASE(parser);
@ -101,9 +108,21 @@
return self;
}
- (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
{
if (NSXMLDocumentKind == kind)
{
/* Create holder for internal instance variables so that we'll have
* all our ivars available rather than just those of the superclass.
*/
GS_CREATE_INTERNAL(NSXMLDocument)
}
return [super initWithKind: kind options: theOptions];
}
- (id) initWithRootElement: (NSXMLElement*)element
{
if ([_children containsObject: element] || [element parent] != nil)
if ([element parent] != nil)
{
[NSException raise: NSInternalInconsistencyException
format: @"%@ cannot be used as root of %@",
@ -132,56 +151,56 @@
- (BOOL) isStandalone
{
return _standalone;
return internal->standalone;
}
- (NSString*) MIMEType
{
return _MIMEType;
return internal->MIMEType;
}
- (NSXMLElement*) rootElement
{
return _rootElement;
return internal->rootElement;
}
- (void) setCharacterEncoding: (NSString*)encoding
{
ASSIGNCOPY(_encoding, encoding);
ASSIGNCOPY(internal->encoding, encoding);
}
- (void) setDocumentContentKind: (NSXMLDocumentContentKind)kind
{
_contentKind = kind;
internal->contentKind = kind;
}
- (void) setDTD: (NSXMLDTD*)documentTypeDeclaration
{
ASSIGNCOPY(_docType, documentTypeDeclaration);
ASSIGNCOPY(internal->docType, documentTypeDeclaration);
}
- (void) setMIMEType: (NSString*)MIMEType
{
ASSIGNCOPY(_MIMEType, MIMEType);
ASSIGNCOPY(internal->MIMEType, MIMEType);
}
- (void) setRootElement: (NSXMLNode*)root
{
NSAssert(_rootElement == nil, NSGenericException);
[self insertChild: root atIndex: [_children count]];
_rootElement = (NSXMLElement*)root;
NSAssert(internal->rootElement == nil, NSGenericException);
[self insertChild: root atIndex: [internal->children count]];
internal->rootElement = (NSXMLElement*)root;
}
- (void) setStandalone: (BOOL)standalone
{
_standalone = standalone;
internal->standalone = standalone;
}
- (void) setVersion: (NSString*)version
{
if ([version isEqualToString: @"1.0"] || [version isEqualToString: @"1.1"])
{
ASSIGNCOPY(_version, version);
ASSIGNCOPY(internal->version, version);
}
else
{
@ -192,14 +211,14 @@
- (NSString*) version
{
return _version;
return internal->version;
}
- (void) insertChild: (NSXMLNode*)child atIndex: (NSUInteger)index
{
[child setParent: self];
[(NSMutableArray *)_children insertObject: child atIndex: index];
_childrenHaveMutated = YES;
[(NSMutableArray *)internal->children insertObject: child atIndex: index];
internal->childrenHaveMutated = YES;
}
- (void) insertChildren: (NSArray*)children atIndex: (NSUInteger)index
@ -215,15 +234,15 @@
- (void) removeChildAtIndex: (NSUInteger)index
{
[(NSMutableArray *)_children removeObjectAtIndex: index];
_childrenHaveMutated = YES;
[(NSMutableArray *)internal->children removeObjectAtIndex: index];
internal->childrenHaveMutated = YES;
}
- (void) setChildren: (NSArray*)children
{
unsigned count;
while ((count = [_children count]) > 0)
while ((count = [internal->children count]) > 0)
{
[self removeChildAtIndex: count - 1];
}
@ -232,7 +251,7 @@
- (void) addChild: (NSXMLNode*)child
{
[self insertChild: child atIndex: [_children count]];
[self insertChild: child atIndex: [internal->children count]];
}
- (void) replaceChildAtIndex: (NSUInteger)index withNode: (NSXMLNode*)node
@ -249,7 +268,7 @@
- (NSData*) XMLDataWithOptions: (NSUInteger)options
{
// TODO: Apply options to data.
return _xmlData;
return internal->xmlData;
}
- (id) objectByApplyingXSLT: (NSData*)xslt
@ -295,8 +314,8 @@
NSXMLElement *currentElement =
[[NSXMLElement alloc] initWithName: elementName];
[_elementStack addObject: currentElement];
if (_rootElement == nil)
[internal->elementStack addObject: currentElement];
if (internal->rootElement == nil)
{
[self setRootElement: currentElement];
}
@ -310,12 +329,12 @@
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([_elementStack count] > 0)
if ([internal->elementStack count] > 0)
{
NSXMLElement *currentElement = [_elementStack lastObject];
NSXMLElement *currentElement = [internal->elementStack lastObject];
if ([[currentElement name] isEqualToString: elementName])
{
[_elementStack removeLastObject];
[internal->elementStack removeLastObject];
}
}
}
@ -323,7 +342,7 @@
- (void) parser: (NSXMLParser *)parser
foundCharacters: (NSString *)string
{
NSXMLElement *currentElement = [_elementStack lastObject];
NSXMLElement *currentElement = [internal->elementStack lastObject];
[currentElement setStringValue: string];
}
@end

View file

@ -26,13 +26,19 @@
#import "NSXMLPrivate.h"
#define GSInternal NSXMLElementInternal
#include "GSInternal.h"
GS_PRIVATE_INTERNAL(NSXMLElement)
@implementation NSXMLElement
- (void) dealloc
{
[_attributes release];
[_namespaces release];
[_children release];
if (GS_EXISTS_INTERNAL && _internal != nil)
{
[internal->attributes release];
[internal->namespaces release];
}
[super dealloc];
}
@ -43,26 +49,40 @@
- (id) initWithName: (NSString*)name URI: (NSString*)URI
{
if ((self = [super initWithKind:NSXMLElementKind]) != nil)
/* Create holder for internal instance variables so that we'll have
* all our ivars available rather than just those of the superclass.
*/
GS_CREATE_INTERNAL(NSXMLElement)
if ((self = [super initWithKind: NSXMLElementKind]) != nil)
{
ASSIGN(_name, name);
_attributes = [[NSMutableDictionary alloc] initWithCapacity: 10];
_namespaces = [[NSMutableArray alloc] initWithCapacity: 10];
_children = [[NSMutableArray alloc] initWithCapacity: 10];
_URI = nil;
ASSIGN(internal->name, name);
internal->attributes = [[NSMutableDictionary alloc] initWithCapacity: 10];
internal->namespaces = [[NSMutableArray alloc] initWithCapacity: 10];
}
return self;
}
- (id) initWithName: (NSString*)name stringValue: (NSString*)string
{
if([self initWithName: name URI: nil] != nil)
if ([self initWithName: name URI: nil] != nil)
{
[self setObjectValue: string];
}
return nil;
}
- (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
{
if (NSXMLElementKind == kind)
{
/* Create holder for internal instance variables so that we'll have
* all our ivars available rather than just those of the superclass.
*/
GS_CREATE_INTERNAL(NSXMLElement)
}
return [super initWithKind: kind options: theOptions];
}
- (id) initWithXMLString: (NSString*)string error: (NSError**)error
{
[self notImplemented: _cmd];
@ -83,13 +103,13 @@
- (void) addAttribute: (NSXMLNode*)attribute
{
[_attributes setObject: attribute
[internal->attributes setObject: attribute
forKey: [attribute name]];
}
- (void) removeAttributeForName: (NSString*)name
{
[_attributes removeObjectForKey: name];
[internal->attributes removeObjectForKey: name];
}
- (void) setAttributes: (NSArray*)attributes
@ -105,17 +125,17 @@
- (void) setAttributesAsDictionary: (NSDictionary*)attributes
{
ASSIGN(_attributes, [attributes mutableCopy]);
ASSIGN(internal->attributes, [attributes mutableCopy]);
}
- (NSArray*) attributes
{
return [_attributes allValues];
return [internal->attributes allValues];
}
- (NSXMLNode*) attributeForName: (NSString*)name
{
return [_attributes objectForKey: name];
return [internal->attributes objectForKey: name];
}
- (NSXMLNode*) attributeForLocalName: (NSString*)localName
@ -142,11 +162,11 @@
- (NSArray*) namespaces
{
if (_namespaces == nil)
if (internal->namespaces == nil)
{
[self notImplemented: _cmd];
}
return _namespaces;
return internal->namespaces;
}
- (NSXMLNode*) namespaceForPrefix: (NSString*)name
@ -185,19 +205,22 @@
- (void) removeChildAtIndex: (NSUInteger)index
{
[_children removeObjectAtIndex: index];
[internal->children removeObjectAtIndex: index];
}
- (void) setChildren: (NSArray*)children
{
ASSIGN(_children, [children mutableCopy]);
_childrenHaveMutated = YES;
NSMutableArray *c = [children mutableCopy];
ASSIGN(internal->children, c);
[c release];
internal->childrenHaveMutated = YES;
}
- (void) addChild: (NSXMLNode*)child
{
[_children addObject: child];
_childrenHaveMutated = YES;
[internal->children addObject: child];
internal->childrenHaveMutated = YES;
}
- (void) replaceChildAtIndex: (NSUInteger)index withNode: (NSXMLNode*)node
@ -222,7 +245,7 @@
// get the attributes...
en = [[self attributes] objectEnumerator];
while((object = [en nextObject]) != nil)
while ((object = [en nextObject]) != nil)
{
[result appendString: @" "];
[result appendString: [object XMLStringWithOptions: options]];
@ -234,7 +257,7 @@
// Iterate over the children...
en = [[self children] objectEnumerator];
while((object = [en nextObject]) != nil)
while ((object = [en nextObject]) != nil)
{
[result appendString: @" "];
[result appendString: [object XMLStringWithOptions: options]];

View file

@ -24,36 +24,17 @@
#import "common.h"
/*
* Description of internal ivars:
* - `children': The primary storage for the descendant nodes. We use an NSArray
* here until somebody finds out it's not fast enough.
* - `childCount': For efficiency, we cache the count. This means we need to
* update it whenever the children change.
* - `previousSibling', `nextSibling': Tree walking is a common operation for
* XML. [_parent->internal->children objectAtIndex: index + 1] would be a
* straightforward way to obtain the next sibling of the node, but it hurts
* performance quite a bit. So we cache the siblings and update them when the
* nodes are changed.
*/
#define GS_NSXMLNode_IVARS \
NSMutableArray *children; \
NSUInteger childCount; \
NSXMLNode *previousSibling; \
NSXMLNode *nextSibling; \
NSUInteger options;
#import "NSXMLPrivate.h"
#define GSInternal NSXMLNodeInternal
#include "GSInternal.h"
@class NSXMLNode;
GS_PRIVATE_INTERNAL(NSXMLNode)
#import "NSXMLPrivate.h"
@implementation NSXMLNode (Private)
- (void) setParent: (NSXMLNode *)node
{
ASSIGN(_parent,node);
ASSIGN(internal->parent,node);
}
@end
@ -226,31 +207,43 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (id) copyWithZone: (NSZone*)zone
{
return NSCopyObject(self,0,zone);
id c = [[self class] allocWithZone: zone];
c = [c initWithKind: internal->kind options: internal->options];
[c setName: [self name]];
[c setURI: [self URI]];
[c setObjectValue: [self objectValue]];
[c setStringValue: [self stringValue]];
return c;
}
- (void) dealloc
{
[self detach];
[internal->children release];
GS_DESTROY_INTERNAL(NSXMLNode);
[_objectValue release];
[_stringValue release];
if (GS_EXISTS_INTERNAL)
{
[self detach];
[internal->name release];
[internal->URI release];
[internal->children release];
[internal->objectValue release];
[internal->stringValue release];
GS_DESTROY_INTERNAL(NSXMLNode);
}
[super dealloc];
}
- (void) detach
{
if (_parent != nil)
if (internal->parent != nil)
{
[(NSXMLElement*)_parent removeChildAtIndex: _index];
_parent = nil;
[(NSXMLElement*)internal->parent removeChildAtIndex: internal->index];
internal->parent = nil;
}
}
- (NSUInteger) index
{
return _index;
return internal->index;
}
- (id) init
@ -267,44 +260,37 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (id) initWithKind: (NSXMLNodeKind)kind options: (NSUInteger)theOptions
{
Class theSubclass = [NSXMLNode class];
if (nil == (self = [super init]))
{
return nil;
}
GS_CREATE_INTERNAL(NSXMLNode)
/*
* We find the correct subclass for specific node kinds:
*/
switch (kind)
{
case NSXMLDocumentKind:
{
theSubclass = [NSXMLDocument class];
break;
}
case NSXMLElementKind:
{
theSubclass = [NSXMLElement class];
break;
}
case NSXMLDTDKind:
{
theSubclass = [NSXMLDTD class];
break;
}
case NSXMLEntityDeclarationKind:
case NSXMLElementDeclarationKind:
case NSXMLNotationDeclarationKind:
{
theSubclass = [NSXMLDTDNode class];
break;
}
default:
{
break;
}
}
/*
@ -319,12 +305,14 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
options: theOptions];
}
/*
* If we are initializing for the correct class, we can actually perform
/* Create holder for internal instance variables if needed.
*/
GS_CREATE_INTERNAL(NSXMLNode)
/* If we are initializing for the correct class, we can actually perform
* initializations:
*/
_kind = kind;
internal->kind = kind;
internal->options = theOptions;
internal->children = [NSMutableArray new];
return self;
@ -332,18 +320,18 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (NSXMLNodeKind) kind
{
return _kind;
return internal->kind;
}
- (NSUInteger) level
{
NSUInteger level = 0;
NSXMLNode *tmp = _parent;
NSXMLNode *tmp = internal->parent;
while (tmp != nil)
{
level++;
tmp = tmp->_parent;
tmp = GSIVar(tmp, parent);
}
return level;
}
@ -355,12 +343,12 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (NSString*) name
{
return _name;
return internal->name;
}
- (NSXMLNode*) _nodeFollowingInNaturalDirection: (BOOL)forward
{
NSXMLNode *ancestor = _parent;
NSXMLNode *ancestor = internal->parent;
NSXMLNode *candidate = nil;
/* Node walking is a depth-first thingy. Hence, we consider children first: */
@ -399,7 +387,7 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
{
candidate = [ancestor previousSibling];
}
ancestor = ancestor->_parent;
ancestor = GSIVar(ancestor, parent);
}
/* No children, no next siblings, no next siblings for any ancestor: We are
@ -410,8 +398,8 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
}
/* Sanity check: Namespace and attribute nodes are skipped: */
if ((NSXMLAttributeKind == candidate->_kind)
|| (NSXMLNamespaceKind == candidate->_kind))
if ((NSXMLAttributeKind == GSIVar(candidate, kind))
|| (NSXMLNamespaceKind == GSIVar(candidate, kind)))
{
return [candidate _nodeFollowingInNaturalDirection: forward];
}
@ -430,12 +418,12 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (id) objectValue
{
return _objectValue;
return internal->objectValue;
}
- (NSXMLNode*) parent
{
return _parent;
return internal->parent;
}
- (NSString*) prefix
@ -456,26 +444,27 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (NSXMLDocument*) rootDocument
{
NSXMLNode *ancestor = _parent;
NSXMLNode *ancestor = internal->parent;
/*
* Short-circuit evaluation gurantees that the nil-pointer is not
* dereferenced:
*/
while ((ancestor != nil) && (NSXMLDocumentKind != ancestor->_kind))
while ((ancestor != nil)
&& (NSXMLDocumentKind != GSIVar(ancestor, kind)))
{
ancestor = ancestor->_parent;
ancestor = GSIVar(ancestor, parent);
}
return (NSXMLDocument*)ancestor;
}
- (NSString*) stringValue
{
return _stringValue;
return internal->stringValue;
}
- (NSString*) URI
{
return _URI; // FIXME ... fetch from libxml
return internal->URI; // FIXME ... fetch from libxml
}
- (NSString*) XMLString
@ -488,7 +477,7 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
NSMutableString *returnValue = [NSMutableString string];
NSXMLNodeKind kind = [self kind];
if(kind == NSXMLAttributeKind)
if (kind == NSXMLAttributeKind)
{
[returnValue appendString: [self name]];
[returnValue appendString: @"=\""];
@ -505,12 +494,12 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (void) setObjectValue: (id)value
{
ASSIGN(_objectValue, value);
ASSIGN(internal->objectValue, value);
}
- (void) setName: (NSString *)name
{
ASSIGN(_name, name);
ASSIGNCOPY(internal->name, name);
}
- (void) setStringValue: (NSString*)string
@ -520,18 +509,19 @@ GS_PRIVATE_INTERNAL(NSXMLNode)
- (void) setURI: (NSString*)URI
{
ASSIGN(_URI, URI);
ASSIGNCOPY(internal->URI, URI);
}
- (void) setStringValue: (NSString*)string resolvingEntities: (BOOL)resolve
{
if(resolve == NO)
if (resolve == NO)
{
ASSIGN(_stringValue, string);
ASSIGN(internal->stringValue, string);
}
else
{
ASSIGN(_stringValue, string); // need to actually resolve entities...
// need to actually resolve entities...
ASSIGN(internal->stringValue, string);
}
}

View file

@ -26,11 +26,94 @@
#define _INCLUDED_NSXMLPRIVATE_H
#import "config.h"
#import "GNUstepBase/GSConfig.h"
#define EXPOSE_NSXMLDTD_IVARS 1
#define EXPOSE_NSXMLDTDNode_IVARS 1
#define EXPOSE_NSXMLDocument_IVARS 1
#define EXPOSE_NSXMLElement_IVARS 1
#define EXPOSE_NSXMLNode_IVARS 1
/*
* Description of internal ivars:
* - `children': The primary storage for the descendant nodes. We use an NSArray
* here until somebody finds out it's not fast enough.
* - `childCount': For efficiency, we cache the count. This means we need to
* update it whenever the children change.
* - `previousSibling', `nextSibling': Tree walking is a common operation for
* XML. [parent->children objectAtIndex: index + 1] would be a
* straightforward way to obtain the next sibling of the node, but it hurts
* performance quite a bit. So we cache the siblings and update them when the
* nodes are changed.
*/
#define GS_NSXMLNode_IVARS \
void *handle; \
NSUInteger kind; \
NSXMLNode *parent; \
NSUInteger index; \
id objectValue; \
NSString *stringValue; \
NSString *name; \
NSString *URI; \
NSMutableArray *children; \
NSUInteger childCount; \
NSXMLNode *previousSibling; \
NSXMLNode *nextSibling; \
NSUInteger options; \
/* When using the non-fragile ABI, the instance variables are exposed to the
* compiler within the class declaration, so we don't need to incorporate
* superclass variables into the subclass declaration.
* But with the fragile ABI we need to allocate a single internal structure
* containing the private variables for both the subclass and the superclass.
*/
#if GS_NONFRAGILE
#define SUPERIVARS(X)
#else
#define SUPERIVARS(X) X
#endif
#define GS_NSXMLDTD_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \
NSString *publicID; \
NSString *systemID; \
BOOL childrenHaveMutated; \
BOOL modified; \
NSMutableDictionary *entities; \
NSMutableDictionary *elements; \
NSMutableDictionary *notations; \
NSMutableDictionary *attributes; \
NSString *original; \
#define GS_NSXMLDTDNode_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \
NSUInteger DTDKind; \
NSString *notationName; \
NSString *publicID; \
NSString *systemID; \
#define GS_NSXMLElement_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \
NSMutableDictionary *attributes; \
NSMutableArray *namespaces; \
BOOL childrenHaveMutated; \
NSInteger prefixIndex; \
#define GS_NSXMLDocument_IVARS SUPERIVARS(GS_NSXMLNode_IVARS) \
NSString *encoding; \
NSString *version; \
NSXMLDTD *docType; \
BOOL childrenHaveMutated; \
BOOL standalone; \
NSXMLElement *rootElement; \
NSString *MIMEType; \
NSUInteger fidelityMask; \
NSInteger contentKind; \
NSMutableArray *elementStack; \
NSData *xmlData; \
#import "Foundation/NSArray.h"
#import "Foundation/NSData.h"
#import "Foundation/NSDebug.h"