Merge pull request #130 from triplef/add-nsxmlparser-stream-support

Implement -[NSXMLParser initWithStream:].
This commit is contained in:
rfm 2020-05-06 14:08:39 +01:00 committed by GitHub
commit ca2abf51f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 154 additions and 43 deletions

View file

@ -1,3 +1,12 @@
2020-04-07 Frederik Seiffert <frederik@algoriddim.com>
* Headers/Foundation/NSXMLParser.h:
* Headers/GNUstepBase/GSXML.h:
* Source/Additions/GSXML.m:
* Source/NSXMLParser.m:
* Tests/base/NSXMLParser/parse.m:
Implement -[NSXMLParser initWithStream:].
2020-04-26 Fred Kiefer <fredkiefer@gmx.de>
* Source/NSLocale.m: Respect NSLocaleCalendarIdentifier if

View file

@ -36,7 +36,7 @@
extern "C" {
#endif
@class NSData, NSDictionary, NSError, NSString, NSURL;
@class NSData, NSDictionary, NSError, NSInputStream, NSString, NSURL;
/**
* Domain for errors
@ -100,12 +100,17 @@ GS_EXPORT NSString* const NSXMLParserErrorDomain;
/**
* Convenience method fetching data from anURL.<br />
*/
- (id) initWithContentsOfURL: (NSURL*)anURL;
- (instancetype) initWithContentsOfURL: (NSURL*)anURL;
/** <init />
* Initialises the parser with the specified xml data.
*/
- (id) initWithData: (NSData*)data;
- (instancetype) initWithData: (NSData*)data;
/**
* Initialises the parser with the specified input stream.
*/
- (instancetype) initWithStream: (NSInputStream*)stream;
/**
* Parses the supplied data and returns YES on success, NO otherwise.

View file

@ -42,6 +42,7 @@
#import <Foundation/NSObject.h>
#import <Foundation/NSString.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSStream.h>
#else
#import <Foundation/Foundation.h>
#endif
@ -222,6 +223,8 @@ extern "C" {
withContentsOfURL: (NSURL*)url;
- (id) initWithSAXHandler: (GSSAXHandler*)handler
withData: (NSData*)data;
- (id) initWithSAXHandler: (GSSAXHandler*)handler
withInputStream: (NSInputStream*)stream;
- (BOOL) keepBlanks: (BOOL)yesno;
- (NSInteger) lineNumber;

View file

@ -910,7 +910,6 @@ NSXMLNodeOptions:
NSXMLParser:
@class NSInputStream
- initWithStream:
- parseError
-------------------------------------------------------------
NSZone:

View file

@ -172,6 +172,19 @@ setupCache()
}
}
static int xmlNSInputStreamReadCallback(void *context, char *buffer, int len)
{
NSInputStream *stream = (NSInputStream *)context;
return [stream read: (uint8_t *)buffer maxLength: len];
}
static int xmlNSInputStreamCloseCallback (void *context)
{
NSInputStream *stream = (NSInputStream *)context;
[stream close];
return 0;
}
static xmlParserInputPtr
loadEntityFunction(const unsigned char *url, const unsigned char *eid,
void *ctx);
@ -2102,6 +2115,31 @@ static NSString *endMarker = @"At end of incremental parse";
return self;
}
/**
* <p>
* Initialisation of a new Parser with SAX handler (if not nil)
* by calling -initWithSAXHandler:
* </p>
* <p>
* Sets the input source for the parser to be the specified input stream,
* so parsing of the entire document will be performed rather than
* incremental parsing.
* </p>
*/
- (id) initWithSAXHandler: (GSSAXHandler*)handler
withInputStream: (NSInputStream*)stream
{
if (stream == nil || [stream isKindOfClass: [NSInputStream class]] == NO)
{
NSLog(@"Bad NSInputStream passed to initialize GSXMLParser");
DESTROY(self);
return nil;
}
src = RETAIN(stream);
self = [self initWithSAXHandler: handler];
return self;
}
/**
* Set and return the previous value for blank text nodes support.
* ignorableWhitespace nodes are only generated when running
@ -2167,7 +2205,8 @@ static NSString *endMarker = @"At end of incremental parse";
return NO;
}
if ([src isKindOfClass: [NSData class]])
if ([src isKindOfClass: [NSData class]]
|| [src isKindOfClass: [NSInputStream class]])
{
}
else if ([src isKindOfClass: NSString_class])
@ -2194,14 +2233,22 @@ static NSString *endMarker = @"At end of incremental parse";
}
else
{
NSLog(@"source for [-parse] must be NSString, NSData or NSURL type");
NSLog(@"Source for [-parse] must be NSString, NSData, NSInputStream, or"
@" NSURL type");
return NO;
}
tmp = RETAIN(src);
ASSIGN(src, endMarker);
[self _parseChunk: tmp];
[self _parseChunk: nil];
if ([tmp isKindOfClass: [NSInputStream class]])
{
xmlParseDocument(lib);
}
else
{
[self _parseChunk: tmp];
[self _parseChunk: nil];
}
RELEASE(tmp);
if (((xmlParserCtxtPtr)lib)->wellFormed != 0
@ -2382,7 +2429,19 @@ static NSString *endMarker = @"At end of incremental parse";
{
file = ".";
}
lib = (void*)xmlCreatePushParserCtxt([saxHandler lib], NULL, 0, 0, file);
if ([src isKindOfClass: [NSInputStream class]])
{
[(NSInputStream*)src open];
lib = (void*)xmlCreateIOParserCtxt([saxHandler lib], NULL,
xmlNSInputStreamReadCallback, xmlNSInputStreamCloseCallback,
(void*)src, XML_CHAR_ENCODING_NONE);
}
else
{
lib = (void*)xmlCreatePushParserCtxt([saxHandler lib], NULL, 0, 0, file);
}
if (lib == NULL)
{
NSLog(@"Failed to create libxml parser context");

View file

@ -480,16 +480,11 @@ static NSNull *null = nil;
- (id) initWithContentsOfURL: (NSURL*)anURL
{
NSData *d = [NSData dataWithContentsOfURL: anURL];
if (d == nil)
{
DESTROY(self);
}
else
{
self = [self initWithData: d];
}
_handler = [NSXMLSAXHandler new];
[myHandler _setOwner: self];
_parser = [[GSXMLParser alloc] initWithSAXHandler: myHandler
withContentsOfURL: anURL];
[(GSXMLParser*)_parser substituteEntities: YES];
return self;
}
@ -497,7 +492,18 @@ static NSNull *null = nil;
{
_handler = [NSXMLSAXHandler new];
[myHandler _setOwner: self];
_parser = [[GSXMLParser alloc] initWithSAXHandler: myHandler withData: data];
_parser = [[GSXMLParser alloc] initWithSAXHandler: myHandler
withData: data];
[(GSXMLParser*)_parser substituteEntities: YES];
return self;
}
- (id) initWithStream: (NSInputStream*)stream
{
_handler = [NSXMLSAXHandler new];
[myHandler _setOwner: self];
_parser = [[GSXMLParser alloc] initWithSAXHandler: myHandler
withInputStream: stream];
[(GSXMLParser*)_parser substituteEntities: YES];
return self;
}

View file

@ -1,6 +1,7 @@
#import "ObjectTesting.h"
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSFileManager.h>
#import <Foundation/NSStream.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSXMLParser.h>
#include <string.h>
@ -236,17 +237,10 @@ static BOOL setShouldReportNamespacePrefixes = YES;
static BOOL setShouldResolveExternalEntities = NO;
static BOOL
testParse(NSData *xml, NSString *expect)
testParser(NSXMLParser *parser, NSString *expect)
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
Handler *handler;
NSXMLParser *parser;
Class c = NSClassFromString(@"GSSloppyXMLParser");
c = Nil;
if (Nil == c) c = [NSXMLParser class];
parser = [[c alloc] initWithData: xml];
Handler *handler;
[parser setShouldProcessNamespaces: setShouldProcessNamespaces];
[parser setShouldReportNamespacePrefixes: setShouldReportNamespacePrefixes];
[parser setShouldResolveExternalEntities: setShouldResolveExternalEntities];
@ -257,7 +251,6 @@ testParse(NSData *xml, NSString *expect)
{
NSLog(@"Parsing failed: %@ at %ld on %ld", [parser parserError],
(long)[parser columnNumber], (long)[parser lineNumber]);
[arp release];
return NO;
}
else
@ -265,22 +258,55 @@ testParse(NSData *xml, NSString *expect)
if (NO == [[handler description] isEqual: expect])
{
NSLog(@"######## Expected:\n%@\n######## Parsed:\n%@\n########\n",
expect, [handler description]);
[arp release];
expect, [handler description]);
return NO;
}
}
[arp release];
return YES;
}
static BOOL
testParseData(NSData *xml, NSString *expect)
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSXMLParser *parser;
Class c = NSClassFromString(@"GSSloppyXMLParser");
BOOL result;
c = Nil;
if (Nil == c) c = [NSXMLParser class];
parser = [[c alloc] initWithData: xml];
result = testParser(parser, expect);
[arp release];
return result;
}
static BOOL
testParseCString(const char *xmlBytes, NSString *expect)
{
NSData *xml;
xml = [NSData dataWithBytes: xmlBytes length: strlen(xmlBytes)];
return testParse(xml, expect);
return testParseData(xml, expect);
}
static BOOL
testParseStream(NSInputStream *stream, NSString *expect)
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
NSXMLParser *parser;
Class c = NSClassFromString(@"GSSloppyXMLParser");
BOOL result;
c = Nil;
if (Nil == c) c = [NSXMLParser class];
parser = [[c alloc] initWithStream: stream];
result = testParser(parser, expect);
[arp release];
return YES;
}
int main()
@ -305,18 +331,22 @@ int main()
while ((xmlName = [dir nextObject]) != nil)
{
if ([[xmlName pathExtension] isEqualToString: @"xml"])
{
NSString *xmlPath;
{
NSString *xmlPath;
NSData *xmlData;
NSString *result;
NSInputStream *stream;
xmlPath = [@"ParseData" stringByAppendingPathComponent: xmlName];
str = [xmlPath stringByDeletingPathExtension];
str = [str stringByAppendingPathExtension: @"result"];
xmlPath = [@"ParseData" stringByAppendingPathComponent: xmlName];
str = [xmlPath stringByDeletingPathExtension];
str = [str stringByAppendingPathExtension: @"result"];
xmlData = [NSData dataWithContentsOfFile: xmlPath];
result = [NSString stringWithContentsOfFile: str];
PASS((testParse(xmlData, result)), "%s", [xmlName UTF8String])
}
PASS((testParseData(xmlData, result)), "parse data: %s", [xmlName UTF8String])
stream = [NSInputStream inputStreamWithFileAtPath:xmlPath];
PASS((testParseStream(stream, result)), "parse stream: %s", [xmlName UTF8String])
}
}
{
@ -335,7 +365,7 @@ parserDidEndDocument:\n\
@"<file>&amp;&foo;&#65;</file>", [mgr currentDirectoryPath]];
dat = [str dataUsingEncoding: NSUTF8StringEncoding];
PASS((testParse(dat, exp)), "external entity")
PASS((testParseData(dat, exp)), "external entity")
}
[arp release]; arp = nil;