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 */; };
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 */; };
E8FB779E1971E5AA00E0557D /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8FB779D1971E5AA00E0557D /* main.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@ -93,7 +92,6 @@
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>"; };
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 */
/* Begin PBXFrameworksBuildPhase section */
@ -137,7 +135,6 @@
isa = PBXGroup;
children = (
E8C667EB19757405004EFA0C /* Expat.swift */,
E8FB779D1971E5AA00E0557D /* main.swift */,
E8FB77431971609A00E0557D /* SwiftyExpat.h */,
E8FB775E1971667F00E0557D /* expat */,
E8FB77411971609A00E0557D /* Supporting Files */,
@ -343,7 +340,6 @@
files = (
E8FB77811971667F00E0557D /* xmltok.c in Sources */,
E8FB777E1971667F00E0557D /* xmlparse.c in Sources */,
E8FB779E1971E5AA00E0557D /* main.swift in Sources */,
E8C667EC19757405004EFA0C /* Expat.swift in Sources */,
E8FB777F1971667F00E0557D /* xmlrole.c in Sources */,
);

View File

@ -14,7 +14,8 @@
*/
class Expat : OutputStream {
let parser : XML_Parser
let parser : XML_Parser
var isClosed = false
init(encoding: String = "UTF-8", nsSeparator: Character = ":") {
let sepUTF8 = ("" + nsSeparator).utf8
@ -31,6 +32,7 @@ class Expat : OutputStream {
parser = newParser
}
deinit {
println("freeing parser ...")
XML_ParserFree(parser)
}
@ -38,9 +40,8 @@ class Expat : OutputStream {
/* feed the parser */
func write(cs: CString) {
let cslen = strlen(cs)
let isFinal = cslen == 0
XML_Parse(parser, cs, Int32(cslen), isFinal ? 1 : 0)
let cslen = strlen(cs)
XML_Parse(parser, cs, Int32(cslen), 0)
}
func write(s: String) {
@ -48,7 +49,32 @@ class Expat : OutputStream {
}
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 {
XML_SetStartElementHandler(parser) {
// void *userData, const XML_Char *name, const XML_Char **atts
( userData, name, attrs ) in
_, name, attrs in
let sName = String.fromCString(name)! // unwrap, must be set
var sAttrs = [ String : String]()
@ -77,4 +102,30 @@ class Expat : OutputStream {
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
# define EXPAT_SET_CALLBACK(__VAR__, __TYPE__, __ARG__) \
(__VAR__ = (__TYPE__)Block_copy(__ARG__))
({ if (__VAR__ != NULL) Block_release(__VAR__); \
__VAR__ = (__TYPE__)Block_copy(__ARG__); })
#else
# define EXPAT_SET_CALLBACK(__VAR__, __TYPE__, __ARG___) (__VAR == __ARG__)
#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

@ -12,25 +12,37 @@ import SwiftyExpat
class SwiftyExpatTests: XCTestCase {
var p : Expat! = nil
override func 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() {
p = nil
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
func testSimpleParsing() {
XCTAssert(true, "Pass")
SwiftyExpat.testit()
let testXML = "<hello xmlns='YoYo' a='5'><x>world</x></hello>"
p.write(testXML)
p.close() // EOF
}
/*
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock() {
// Put the code you want to measure the time of here.
}
}
*/
}