/*
* Copyright (c) 2008 - 2009
* Jonathan Schleifer <js@webkeks.org>
*
* All rights reserved.
*
* This file is part of ObjFW. It may be distributed under the terms of the
* Q Public License 1.0, which can be found in the file LICENSE included in
* the packaging of this file.
*/
#include "config.h"
#include <string.h>
#import "OFXMLParser.h"
#import "OFAutoreleasePool.h"
#import "OFString.h"
#import "OFExceptions.h"
#import "main.h"
static OFString *module = @"OFXMLParser";
static int i = 0;
enum event_type {
TAG_START,
TAG_END,
STRING,
COMMENT
};
static void
callback(enum event_type et, OFString *name, OFString *prefix, OFString *ns,
OFArray *attrs, OFString *string, OFString *comment)
{
OFString *msg;
id *carray;
size_t count;
i++;
msg = [OFString stringWithFormat: @"Parsing part #%d", i];
switch (i) {
case 1:
case 5:
TEST(msg, et == STRING && [string isEqual: @"bar"])
break;
case 2:
/* FIXME: Namespace */
carray = [attrs cArray];
count = [attrs count];
TEST(msg, et == TAG_START && [name isEqual: @"bar"] &&
[prefix isEqual: @"foo"] && ns == nil &&
attrs != nil && count == 2 &&
/* Attribute 1 */
[[carray[0] name] isEqual: @"bar"] &&
[carray[0] prefix] == nil &&
[[carray[0] stringValue] isEqual: @"b&az"] &&
[carray[0] namespace] == nil &&
/* Attribute 2 */
[[carray[1] name] isEqual: @"qux"] &&
[[carray[1] prefix] isEqual: @"qux"] &&
[[carray[1] stringValue] isEqual: @" quux "] &&
[carray[1] namespace] == nil)
break;
case 3:
TEST(msg, et == STRING && [string isEqual: @"foo<bar"])
break;
case 4:
TEST(msg, et == TAG_START && [name isEqual: @"qux"] &&
prefix == nil && ns == nil)
break;
case 6:
carray = [attrs cArray];
count = [attrs count];
TEST(msg, et == TAG_START && [name isEqual: @"baz"] &&
prefix == nil && ns == nil && attrs != nil && count == 2 &&
/* Attribute 1 */
[[carray[0] name] isEqual: @"name"] &&
[carray[0] prefix] == nil &&
[[carray[0] stringValue] isEqual: @""] &&
[carray[0] namespace] == nil &&
/* Attribute 2 */
[[carray[1] name] isEqual: @"test"] &&
[carray[1] prefix] == nil &&
[[carray[1] stringValue] isEqual: @"foobar"] &&
[carray[1] namespace] == nil)
break;
case 7:
TEST(msg, et == TAG_END && [name isEqual: @"baz"] &&
prefix == nil && ns == nil)
break;
case 8:
TEST(msg, et == STRING && [string isEqual: @"quxbar"])
break;
case 9:
TEST(msg, et == TAG_END && [name isEqual: @"qux"] &&
prefix == nil && ns == nil)
break;
case 10:
/* FIXME: Namespace */
TEST(msg, et == TAG_END && [name isEqual: @"bar"] &&
[prefix isEqual: @"foo"] && ns == nil)
break;
case 11:
TEST(msg, et == COMMENT && [comment isEqual: @"foo bär-baz"])
break;
default:
TEST(msg, NO)
break;
}
}
@interface ParserDelegate: OFObject
@end
@implementation ParserDelegate
- (void)xmlParser: (OFXMLParser*)parser
didStartTagWithName: (OFString*)name
prefix: (OFString*)prefix
namespace: (OFString*)ns
attributes: (OFArray*)attrs
{
callback(TAG_START, name, prefix, ns, attrs, nil, nil);
}
- (void)xmlParser: (OFXMLParser*)parser
didEndTagWithName: (OFString*)name
prefix: (OFString*)prefix
namespace: (OFString*)ns
{
callback(TAG_END, name, prefix, ns, nil, nil, nil);
}
- (void)xmlParser: (OFXMLParser*)parser
foundString: (OFString*)string
{
callback(STRING, nil, nil, nil, nil, string, nil);
}
- (void)xmlParser: (OFXMLParser*)parser
foundComment: (OFString*)comment
{
callback(COMMENT, nil, nil, nil, nil, nil, comment);
}
- (OFString*)xmlParser: (OFXMLParser*)parser
foundUnknownEntityNamed: (OFString*)entity
{
if ([entity isEqual: @"foo"])
return @"foobar";
return nil;
}
@end
void
xmlparser_tests()
{
OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init];
OFXMLParser *parser;
const char *str = "bar<foo:bar bar='b&az' qux:qux=\" quux \">\r\n"
"foo<bar<qux >bar <baz name='' test='&foo;'/> quxbar\r\n</qux>"
"</foo:bar><!-- foo bär-baz -->";
size_t j, len;
TEST(@"+[xmlParser]", (parser = [OFXMLParser xmlParser]))
TEST(@"-[setDelegate:]",
[parser setDelegate: [[[ParserDelegate alloc] init] autorelease]])
/* Simulate a stream where we only get chunks */
len = strlen(str);
for (j = 0; j < len; j+= 2) {
if (j + 2 > len)
[parser parseBuffer: str + j
withSize: 1];
else
[parser parseBuffer: str + j
withSize: 2];
}
TEST(@"Checking if everything was parsed", i == 11)
[pool drain];
}