More callbacks.

This commit is contained in:
Helge Hess 2014-07-15 17:03:59 +02:00
parent b9f0dd9fd2
commit e9f8bc6536
5 changed files with 75 additions and 38 deletions

View File

@ -30,7 +30,6 @@
E8FB77941971767500E0557D /* SwiftyExpatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8FB77931971767500E0557D /* SwiftyExpatTests.swift */; }; E8FB77941971767500E0557D /* SwiftyExpatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8FB77931971767500E0557D /* SwiftyExpatTests.swift */; };
E8FB77951971767500E0557D /* SwiftyExpat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8FB773E1971609A00E0557D /* SwiftyExpat.framework */; }; E8FB77951971767500E0557D /* SwiftyExpat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E8FB773E1971609A00E0557D /* SwiftyExpat.framework */; };
E8FB779C1971E4AB00E0557D /* SwiftyExpat-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = E8FB779B1971E4AB00E0557D /* SwiftyExpat-Bridging-Header.h */; }; E8FB779C1971E4AB00E0557D /* SwiftyExpat-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = E8FB779B1971E4AB00E0557D /* SwiftyExpat-Bridging-Header.h */; };
E8FB779E1971E5AA00E0557D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8FB779D1971E5AA00E0557D /* main.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -93,7 +92,6 @@
E8FB77921971767500E0557D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; E8FB77921971767500E0557D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E8FB77931971767500E0557D /* SwiftyExpatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftyExpatTests.swift; sourceTree = "<group>"; }; E8FB77931971767500E0557D /* SwiftyExpatTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftyExpatTests.swift; sourceTree = "<group>"; };
E8FB779B1971E4AB00E0557D /* SwiftyExpat-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SwiftyExpat-Bridging-Header.h"; sourceTree = "<group>"; }; E8FB779B1971E4AB00E0557D /* SwiftyExpat-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SwiftyExpat-Bridging-Header.h"; sourceTree = "<group>"; };
E8FB779D1971E5AA00E0557D /* main.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -137,7 +135,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
E8C667EB19757405004EFA0C /* Expat.swift */, E8C667EB19757405004EFA0C /* Expat.swift */,
E8FB779D1971E5AA00E0557D /* main.swift */,
E8FB77431971609A00E0557D /* SwiftyExpat.h */, E8FB77431971609A00E0557D /* SwiftyExpat.h */,
E8FB775E1971667F00E0557D /* expat */, E8FB775E1971667F00E0557D /* expat */,
E8FB77411971609A00E0557D /* Supporting Files */, E8FB77411971609A00E0557D /* Supporting Files */,
@ -343,7 +340,6 @@
files = ( files = (
E8FB77811971667F00E0557D /* xmltok.c in Sources */, E8FB77811971667F00E0557D /* xmltok.c in Sources */,
E8FB777E1971667F00E0557D /* xmlparse.c in Sources */, E8FB777E1971667F00E0557D /* xmlparse.c in Sources */,
E8FB779E1971E5AA00E0557D /* main.swift in Sources */,
E8C667EC19757405004EFA0C /* Expat.swift in Sources */, E8C667EC19757405004EFA0C /* Expat.swift in Sources */,
E8FB777F1971667F00E0557D /* xmlrole.c in Sources */, E8FB777F1971667F00E0557D /* xmlrole.c in Sources */,
); );

View File

@ -14,7 +14,8 @@
*/ */
class Expat : OutputStream { class Expat : OutputStream {
let parser : XML_Parser let parser : XML_Parser
var isClosed = false
init(encoding: String = "UTF-8", nsSeparator: Character = ":") { init(encoding: String = "UTF-8", nsSeparator: Character = ":") {
let sepUTF8 = ("" + nsSeparator).utf8 let sepUTF8 = ("" + nsSeparator).utf8
@ -31,6 +32,7 @@ class Expat : OutputStream {
parser = newParser parser = newParser
} }
deinit { deinit {
println("freeing parser ...")
XML_ParserFree(parser) XML_ParserFree(parser)
} }
@ -38,9 +40,8 @@ class Expat : OutputStream {
/* feed the parser */ /* feed the parser */
func write(cs: CString) { func write(cs: CString) {
let cslen = strlen(cs) let cslen = strlen(cs)
let isFinal = cslen == 0 XML_Parse(parser, cs, Int32(cslen), 0)
XML_Parse(parser, cs, Int32(cslen), isFinal ? 1 : 0)
} }
func write(s: String) { func write(s: String) {
@ -48,7 +49,32 @@ class Expat : OutputStream {
} }
func close() { func close() {
if isClosed { return }
let isFinal : Int32 = 1
XML_Parse(parser, "", 0, isFinal)
resetCallbacks()
isClosed = true
}
func resetCallbacks() {
// reset callbacks to fixup any potential cycles
XML_SetElementHandler (parser, nil, nil)
XML_SetCharacterDataHandler (parser, nil)
XML_SetProcessingInstructionHandler(parser, nil)
XML_SetCommentHandler (parser, nil)
XML_SetCdataSectionHandler (parser, nil, nil)
XML_SetDefaultHandler (parser, nil)
XML_SetDefaultHandlerExpand (parser, nil)
XML_SetDoctypeDeclHandler (parser, nil, nil)
XML_SetUnparsedEntityDeclHandler(parser, nil)
XML_SetNotationDeclHandler (parser, nil)
XML_SetNamespaceDeclHandler (parser, nil, nil)
XML_SetNotStandaloneHandler (parser, nil)
XML_SetExternalEntityRefHandler (parser, nil)
XML_SetSkippedEntityHandler (parser, nil)
XML_SetUnknownEncodingHandler (parser, nil, nil)
} }
@ -56,8 +82,7 @@ class Expat : OutputStream {
func onStartElement(cb: ( String, [ String : String ] ) -> Void) -> Self { func onStartElement(cb: ( String, [ String : String ] ) -> Void) -> Self {
XML_SetStartElementHandler(parser) { XML_SetStartElementHandler(parser) {
// void *userData, const XML_Char *name, const XML_Char **atts _, name, attrs in
( userData, name, attrs ) in
let sName = String.fromCString(name)! // unwrap, must be set let sName = String.fromCString(name)! // unwrap, must be set
var sAttrs = [ String : String]() var sAttrs = [ String : String]()
@ -77,4 +102,30 @@ class Expat : OutputStream {
return self return self
} }
func onEndElement(cb: ( String ) -> Void) -> Self {
XML_SetEndElementHandler(parser) { _, name in
let sName = String.fromCString(name)! // unwrap, must be set
cb(sName)
}
return self
}
func onStartNamespace(cb: ( String?, String ) -> Void) -> Self {
XML_SetStartNamespaceDeclHandler(parser) {
_, prefix, uri in
let sPrefix = String.fromCString(prefix)
let sURI = String.fromCString(uri)!
cb(sPrefix, sURI)
}
return self
}
func onEndNamespace(cb: ( String? ) -> Void) -> Self {
XML_SetEndNamespaceDeclHandler(parser) {
_, prefix in
let sPrefix = String.fromCString(prefix)
cb(sPrefix)
}
return self
}
} }

View File

@ -1302,7 +1302,8 @@ XML_GetAttributeInfo(XML_Parser parser)
#ifdef EXPAT_WITH_BLOCKS #ifdef EXPAT_WITH_BLOCKS
# define EXPAT_SET_CALLBACK(__VAR__, __TYPE__, __ARG__) \ # define EXPAT_SET_CALLBACK(__VAR__, __TYPE__, __ARG__) \
(__VAR__ = (__TYPE__)Block_copy(__ARG__)) ({ if (__VAR__ != NULL) Block_release(__VAR__); \
__VAR__ = (__TYPE__)Block_copy(__ARG__); })
#else #else
# define EXPAT_SET_CALLBACK(__VAR__, __TYPE__, __ARG___) (__VAR == __ARG__) # define EXPAT_SET_CALLBACK(__VAR__, __TYPE__, __ARG___) (__VAR == __ARG__)
#endif #endif

View File

@ -1,23 +0,0 @@
//
// main.swift
// SwiftyExpat
//
// Created by Helge Heß on 7/12/14.
// Copyright (c) 2014 Always Right Institute. All rights reserved.
//
import Foundation
func testit() {
println("testing it ...")
var p = Expat()
p.onStartElement { name, attrs in println("name: \(name) \(attrs)") }
let testXML = "<hello a='5'><x>world</x></hello>"
p.write(testXML)
p.write("") // EOF
// XML_SetElementHandler(p, startCB, endCB)
}

View File

@ -11,26 +11,38 @@ import XCTest
import SwiftyExpat import SwiftyExpat
class SwiftyExpatTests: XCTestCase { class SwiftyExpatTests: XCTestCase {
var p : Expat! = nil
override func setUp() { override func setUp() {
super.setUp() super.setUp()
p = Expat()
.onStartElement { name, attrs in println("<\(name) \(attrs)") }
.onEndElement { name in println(">\(name)") }
.onStartNamespace { prefix, uri in println("+NS[\(prefix)] = \(uri)") }
.onEndNamespace { prefix in println("-NS[\(prefix)]") }
} }
override func tearDown() { override func tearDown() {
p = nil
super.tearDown() super.tearDown()
} }
func testExample() { func testSimpleParsing() {
// This is an example of a functional test case.
XCTAssert(true, "Pass") XCTAssert(true, "Pass")
SwiftyExpat.testit()
let testXML = "<hello xmlns='YoYo' a='5'><x>world</x></hello>"
p.write(testXML)
p.close() // EOF
} }
/*
func testPerformanceExample() { func testPerformanceExample() {
// This is an example of a performance test case. // This is an example of a performance test case.
self.measureBlock() { self.measureBlock() {
// Put the code you want to measure the time of here. // Put the code you want to measure the time of here.
} }
} }
*/
} }