1
1
// This source file is part of the Swift.org open source project
2
2
//
3
- // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
3
+ // Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
4
4
// Licensed under Apache License v2.0 with Runtime Library Exception
5
5
//
6
6
// See http://swift.org/LICENSE.txt for license information
@@ -486,8 +486,9 @@ open class XMLParser : NSObject {
486
486
return false
487
487
}
488
488
489
- internal func parseData( _ data: Data ) -> Bool {
489
+ internal func parseData( _ data: Data , lastChunkOfData : Bool = false ) -> Bool {
490
490
_CFXMLInterfaceSetStructuredErrorFunc ( interface, _structuredErrorFunc)
491
+ defer { _CFXMLInterfaceSetStructuredErrorFunc ( interface, nil ) }
491
492
492
493
let handler : _CFXMLInterfaceSAXHandler ? = ( delegate != nil ? _handler : nil )
493
494
let unparsedData : Data
@@ -504,7 +505,7 @@ open class XMLParser : NSObject {
504
505
// If we have not received 4 bytes, save the bomChunk for next pass
505
506
if bomChunk. count < 4 {
506
507
_bomChunk = bomChunk
507
- return false
508
+ return true
508
509
}
509
510
// Prepare options (substitute entities, recover on errors)
510
511
var options = _kCFXMLInterfaceRecover | _kCFXMLInterfaceNoEnt
@@ -520,6 +521,12 @@ open class XMLParser : NSObject {
520
521
let bytes = rawBuffer. baseAddress!. assumingMemoryBound ( to: CChar . self)
521
522
_parserContext = _CFXMLInterfaceCreatePushParserCtxt ( handler, interface, bytes, 4 , nil )
522
523
}
524
+ guard _parserContext != nil else {
525
+ if _parserError == nil {
526
+ _parserError = NSError ( domain: XMLParser . errorDomain, code: ErrorCode . outOfMemoryError. rawValue)
527
+ }
528
+ return false
529
+ } ;
523
530
_CFXMLInterfaceCtxtUseOptions ( _parserContext, options)
524
531
// Prepare the remaining data for parsing
525
532
let dataRange = bomChunk. indices
@@ -532,57 +539,54 @@ open class XMLParser : NSObject {
532
539
533
540
let parseResult = unparsedData. withUnsafeBytes { ( rawBuffer: UnsafeRawBufferPointer ) -> Int32 in
534
541
let bytes = rawBuffer. baseAddress!. assumingMemoryBound ( to: CChar . self)
535
- return _CFXMLInterfaceParseChunk ( _parserContext, bytes, Int32 ( unparsedData. count) , 0 )
542
+ return _CFXMLInterfaceParseChunk ( _parserContext, bytes, Int32 ( unparsedData. count) , lastChunkOfData ? 1 : 0 )
536
543
}
537
544
538
545
let result = _handleParseResult ( parseResult)
539
- _CFXMLInterfaceSetStructuredErrorFunc ( interface, nil )
540
546
return result
541
547
}
542
548
543
- internal func parseFromStream ( ) -> Bool {
549
+ internal func parseFrom ( _ stream : InputStream ) -> Bool {
544
550
var result = true
545
- XMLParser . setCurrentParser ( self )
546
- defer { XMLParser . setCurrentParser ( nil ) }
547
- if let stream = _stream {
548
- stream . open ( )
549
- defer { stream. close ( ) }
550
- let buffer = malloc ( _chunkSize ) ! . bindMemory ( to : UInt8 . self , capacity : _chunkSize )
551
- defer { free ( buffer ) }
552
- var len = stream. read ( buffer, maxLength: _chunkSize)
553
- if len != - 1 {
554
- while len > 0 {
555
- let data = Data ( bytesNoCopy : buffer , count : len , deallocator : . none )
556
- result = parseData ( data )
557
- len = stream . read ( buffer , maxLength : _chunkSize )
558
- }
559
- } else {
551
+
552
+ guard let buffer = malloc ( _chunkSize ) ? . bindMemory ( to : UInt8 . self , capacity : _chunkSize ) else { return false }
553
+ defer { free ( buffer ) }
554
+
555
+ stream. open ( )
556
+ defer { stream . close ( ) }
557
+ parseLoop: while result {
558
+ switch stream. read ( buffer, maxLength: _chunkSize) {
559
+ case let len where len > 0 :
560
+ let data = Data ( bytesNoCopy : buffer , count : len , deallocator : . none )
561
+ result = parseData ( data )
562
+ case 0 :
563
+ result = parseData ( Data ( ) , lastChunkOfData : true )
564
+ break parseLoop
565
+ default : // See SR-13516, should be `case ..<0:`
560
566
result = false
561
- }
562
- } else if var data = _data {
563
- let buffer = malloc ( _chunkSize) !. bindMemory ( to: UInt8 . self, capacity: _chunkSize)
564
- defer { free ( buffer) }
565
- var range = NSRange ( location: 0 , length: min ( _chunkSize, data. count) )
566
- while result {
567
- let chunk = data. withUnsafeMutableBytes { ( rawBuffer: UnsafeMutableRawBufferPointer ) -> Data in
568
- let ptr = rawBuffer. baseAddress!. advanced ( by: range. location)
569
- return Data ( bytesNoCopy: ptr, count: range. length, deallocator: . none)
570
- }
571
- result = parseData ( chunk)
572
- if range. location + range. length >= data. count {
573
- break
567
+ if _parserError == nil {
568
+ _parserError = stream. streamError
574
569
}
575
- range = NSRange ( location: range. location + range. length, length: min ( _chunkSize, data. count - ( range. location + range. length) ) )
570
+
571
+ break parseLoop
576
572
}
577
- } else {
578
- result = false
579
573
}
574
+
580
575
return result
581
576
}
582
577
583
578
// called to start the event-driven parse. Returns YES in the event of a successful parse, and NO in case of error.
584
579
open func parse( ) -> Bool {
585
- return parseFromStream ( )
580
+ XMLParser . setCurrentParser ( self )
581
+ defer { XMLParser . setCurrentParser ( nil ) }
582
+
583
+ if _stream != nil {
584
+ return parseFrom ( _stream!)
585
+ } else if _data != nil {
586
+ return parseData ( _data!, lastChunkOfData: true )
587
+ }
588
+
589
+ return false
586
590
}
587
591
588
592
// called by the delegate to stop the parse. The delegate will get an error message sent to it.
0 commit comments