Index: src/OFXMLParser.h ================================================================== --- src/OFXMLParser.h +++ src/OFXMLParser.h @@ -19,10 +19,11 @@ #import "OFXMLAttribute.h" @class OFXMLParser; @class OFArray; @class OFMutableArray; +@class OFDataArray; @class OFStream; #if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS) typedef void (^of_xml_parser_processing_instructions_block_t)( OFXMLParser *parser, OFString *pi); @@ -158,11 +159,11 @@ OF_XMLPARSER_IN_COMMENT_1, OF_XMLPARSER_IN_COMMENT_2, OF_XMLPARSER_IN_DOCTYPE, OF_XMLPARSER_NUM_STATES } state; - OFMutableString *cache; + OFDataArray *cache; OFString *name; OFString *prefix; OFMutableArray *namespaces; OFMutableArray *attributes; OFString *attributeName; Index: src/OFXMLParser.m ================================================================== --- src/OFXMLParser.m +++ src/OFXMLParser.m @@ -23,10 +23,11 @@ #import "OFXMLParser.h" #import "OFString.h" #import "OFArray.h" #import "OFDictionary.h" +#import "OFDataArray.h" #import "OFXMLAttribute.h" #import "OFStream.h" #import "OFFile.h" #import "OFAutoreleasePool.h" @@ -38,46 +39,53 @@ typedef void (*state_function)(id, SEL, const char*, size_t*, size_t*); static SEL selectors[OF_XMLPARSER_NUM_STATES]; static state_function lookupTable[OF_XMLPARSER_NUM_STATES]; -static void -cache_append(OFMutableString *cache, const char *string, +static OF_INLINE void +cache_append(OFDataArray *cache, const char *string, of_string_encoding_t encoding, size_t length) { if (OF_LIKELY(encoding == OF_STRING_ENCODING_UTF_8)) - [cache appendCStringWithoutUTF8Checking: string - length: length]; + [cache addNItems: length + fromCArray: string]; else { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - [cache appendString: [OFString stringWithCString: string - encoding: encoding - length: length]]; + OFString *tmp = [OFString stringWithCString: string + encoding: encoding + length: length]; + [cache addNItems: [tmp cStringLength] + fromCArray: [tmp cString]]; [pool release]; } } static OFString* -transform_string(OFMutableString *cache, size_t cut, BOOL unescape, +transform_string(OFDataArray *cache, size_t cut, BOOL unescape, OFObject *delegate) { - [cache replaceOccurrencesOfString: @"\r\n" - withString: @"\n"]; - [cache replaceOccurrencesOfString: @"\r" - withString: @"\n"]; + OFMutableString *ret = [OFMutableString + stringWithCString: [cache cArray] + length: [cache count]]; + + [ret replaceOccurrencesOfString: @"\r\n" + withString: @"\n"]; + [ret replaceOccurrencesOfString: @"\r" + withString: @"\n"]; if (cut > 0) { - size_t length = [cache length]; + size_t length = [ret length]; - [cache deleteCharactersFromIndex: length - cut - toIndex: length]; + [ret deleteCharactersFromIndex: length - cut + toIndex: length]; } if (unescape) - return [cache stringByXMLUnescapingWithDelegate: delegate]; - else - return [[cache copy] autorelease]; + return [ret stringByXMLUnescapingWithDelegate: delegate]; + + ret->isa = [OFString class]; + return ret; } static OFString* namespace_for_prefix(OFString *prefix, OFArray *namespaces) { @@ -173,11 +181,11 @@ @try { OFAutoreleasePool *pool; OFMutableDictionary *dict; - cache = [[OFMutableString alloc] init]; + cache = [[OFBigDataArray alloc] init]; previous = [[OFMutableArray alloc] init]; namespaces = [[OFMutableArray alloc] init]; pool = [[OFAutoreleasePool alloc] init]; dict = [OFMutableDictionary dictionaryWithKeysAndObjects: @@ -316,11 +324,11 @@ return; if ((length = *i - *last) > 0) cache_append(cache, buffer + *last, encoding, length); - if ([cache cStringLength] > 0) { + if ([cache count] > 0) { OFString *characters; OFAutoreleasePool *pool; pool = [[OFAutoreleasePool alloc] init]; characters = transform_string(cache, 0, YES, self); @@ -334,11 +342,11 @@ foundCharacters: characters]; [pool release]; } - [cache setToCString: ""]; + [cache removeNItems: [cache count]]; *last = *i + 1; state = OF_XMLPARSER_TAG_OPENED; } @@ -496,11 +504,11 @@ [delegate parser: self foundProcessingInstructions: pi]; [pool release]; - [cache setToCString: ""]; + [cache removeNItems: [cache count]]; *last = *i + 1; state = OF_XMLPARSER_OUTSIDE_TAG; } else level = 0; @@ -509,47 +517,53 @@ /* Inside a tag, no name yet */ - (void)_parseInTagNameWithBuffer: (const char*)buffer i: (size_t*)i last: (size_t*)last { + OFAutoreleasePool *pool; const char *cacheCString, *tmp; size_t length, cacheLength; + OFString *cacheString; if (buffer[*i] != ' ' && buffer[*i] != '\t' && buffer[*i] != '\n' && buffer[*i] != '\r' && buffer[*i] != '>' && buffer[*i] != '/') return; if ((length = *i - *last) > 0) cache_append(cache, buffer + *last, encoding, length); - cacheCString = [cache cString]; - cacheLength = [cache cStringLength]; + pool = [[OFAutoreleasePool alloc] init]; + + cacheCString = [cache cArray]; + cacheLength = [cache count]; + cacheString = [OFString stringWithCString: cacheCString + length: cacheLength]; if ((tmp = memchr(cacheCString, ':', cacheLength)) != NULL) { name = [[OFString alloc] initWithCString: tmp + 1 length: cacheLength - (tmp - cacheCString) - 1]; prefix = [[OFString alloc] initWithCString: cacheCString length: tmp - cacheCString]; } else { - name = [cache copy]; + name = [cacheString copy]; prefix = nil; } if (buffer[*i] == '>' || buffer[*i] == '/') { - OFAutoreleasePool *pool; + OFAutoreleasePool *pool2; OFString *ns; ns = namespace_for_prefix(prefix, namespaces); if (prefix != nil && ns == nil) @throw [OFUnboundNamespaceException newWithClass: isa prefix: prefix]; - pool = [[OFAutoreleasePool alloc] init]; + pool2 = [[OFAutoreleasePool alloc] init]; #if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS) if (elementStartHandler != NULL) elementStartHandler(self, name, prefix, ns, nil); else @@ -572,13 +586,13 @@ namespace: ns]; if ([previous count] == 0) finishedParsing = YES; } else - [previous addObject: [[cache copy] autorelease]]; + [previous addObject: cacheString]; - [pool release]; + [pool2 release]; [name release]; [prefix release]; name = prefix = nil; @@ -585,20 +599,20 @@ state = (buffer[*i] == '/' ? OF_XMLPARSER_EXPECT_CLOSE : OF_XMLPARSER_OUTSIDE_TAG); } else state = OF_XMLPARSER_IN_TAG; + + [pool release]; if (buffer[*i] != '/') { - OFAutoreleasePool *pool; - pool = [[OFAutoreleasePool alloc] init]; [namespaces addObject: [OFMutableDictionary dictionary]]; [pool release]; } - [cache setToCString: ""]; + [cache removeNItems: [cache count]]; *last = *i + 1; } /* Inside a close tag, no name yet */ - (void)_parseInCloseTagNameWithBuffer: (const char*)buffer @@ -606,49 +620,52 @@ last: (size_t*)last { OFAutoreleasePool *pool; const char *cacheCString, *tmp; size_t length, cacheLength; + OFString *cacheString; OFString *ns; if (buffer[*i] != ' ' && buffer[*i] != '\t' && buffer[*i] != '\n' && buffer[*i] != '\r' && buffer[*i] != '>') return; if ((length = *i - *last) > 0) cache_append(cache, buffer + *last, encoding, length); - cacheCString = [cache cString]; - cacheLength = [cache cStringLength]; + pool = [[OFAutoreleasePool alloc] init]; + + cacheCString = [cache cArray]; + cacheLength = [cache count]; + cacheString = [OFString stringWithCString: cacheCString + length: cacheLength]; if ((tmp = memchr(cacheCString, ':', cacheLength)) != NULL) { name = [[OFString alloc] initWithCString: tmp + 1 length: cacheLength - (tmp - cacheCString) - 1]; prefix = [[OFString alloc] initWithCString: cacheCString length: tmp - cacheCString]; } else { - name = [cache copy]; + name = [cacheString copy]; prefix = nil; } - if (![[previous lastObject] isEqual: cache]) + if (![[previous lastObject] isEqual: cacheString]) @throw [OFMalformedXMLException newWithClass: isa parser: self]; [previous removeLastObject]; - [cache setToCString: ""]; + [cache removeNItems: [cache count]]; ns = namespace_for_prefix(prefix, namespaces); if (prefix != nil && ns == nil) @throw [OFUnboundNamespaceException newWithClass: isa prefix: prefix]; - pool = [[OFAutoreleasePool alloc] init]; - #if defined(OF_HAVE_PROPERTIES) && defined(OF_HAVE_BLOCKS) if (elementEndHandler != NULL) elementEndHandler(self, name, prefix, ns); else #endif @@ -759,37 +776,47 @@ /* Looking for attribute name */ - (void)_parseInAttributeNameWithBuffer: (const char*)buffer i: (size_t*)i last: (size_t*)last { + OFAutoreleasePool *pool; + OFMutableString *cacheString; const char *cacheCString, *tmp; size_t length, cacheLength; if (buffer[*i] != '=') return; if ((length = *i - *last) > 0) cache_append(cache, buffer + *last, encoding, length); - [cache deleteEnclosingWhitespaces]; + pool = [[OFAutoreleasePool alloc] init]; + + cacheString = [OFMutableString stringWithCString: [cache cArray] + length: [cache count]]; + [cacheString deleteEnclosingWhitespaces]; + /* Prevent a useless copy later */ + cacheString->isa = [OFString class]; - cacheCString = [cache cString]; - cacheLength = [cache cStringLength]; + cacheCString = [cacheString cString]; + cacheLength = [cacheString cStringLength]; if ((tmp = memchr(cacheCString, ':', cacheLength)) != NULL) { attributeName = [[OFString alloc] initWithCString: tmp + 1 length: cacheLength - (tmp - cacheCString) - 1]; attributePrefix = [[OFString alloc] initWithCString: cacheCString length: tmp - cacheCString]; } else { - attributeName = [cache copy]; + attributeName = [cacheString copy]; attributePrefix = nil; } - [cache setToCString: ""]; + [pool release]; + + [cache removeNItems: [cache count]]; *last = *i + 1; state = OF_XMLPARSER_EXPECT_DELIM; } @@ -845,11 +872,11 @@ namespace: attributePrefix stringValue: attributeValue]]; [pool release]; - [cache setToCString: ""]; + [cache removeNItems: [cache count]]; [attributeName release]; [attributePrefix release]; attributeName = attributePrefix = nil; *last = *i + 1; @@ -964,11 +991,11 @@ [delegate parser: self foundCDATA: CDATA]; [pool release]; - [cache setToCString: ""]; + [cache removeNItems: [cache count]]; *last = *i + 1; state = OF_XMLPARSER_OUTSIDE_TAG; } @@ -1023,11 +1050,11 @@ [delegate parser: self foundComment: comment]; [pool release]; - [cache setToCString: ""]; + [cache removeNItems: [cache count]]; *last = *i + 1; state = OF_XMLPARSER_OUTSIDE_TAG; }