Moved Expat class to own file, made it a class for deinit()

This commit is contained in:
Helge Hess 2014-07-15 16:40:45 +02:00
parent f89ed83dfd
commit b9f0dd9fd2
4 changed files with 89 additions and 61 deletions

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
E8C667EC19757405004EFA0C /* Expat.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8C667EB19757405004EFA0C /* Expat.swift */; };
E8FB77441971609A00E0557D /* SwiftyExpat.h in Headers */ = {isa = PBXBuildFile; fileRef = E8FB77431971609A00E0557D /* SwiftyExpat.h */; settings = {ATTRIBUTES = (Public, ); }; };
E8FB77721971667F00E0557D /* ascii.h in Headers */ = {isa = PBXBuildFile; fileRef = E8FB775F1971667F00E0557D /* ascii.h */; };
E8FB77731971667F00E0557D /* asciitab.h in Headers */ = {isa = PBXBuildFile; fileRef = E8FB77601971667F00E0557D /* asciitab.h */; };
@ -64,6 +65,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
E8C667EB19757405004EFA0C /* Expat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Expat.swift; sourceTree = "<group>"; };
E8FB773E1971609A00E0557D /* SwiftyExpat.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyExpat.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E8FB77421971609A00E0557D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E8FB77431971609A00E0557D /* SwiftyExpat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftyExpat.h; sourceTree = "<group>"; };
@ -134,6 +136,7 @@
E8FB77401971609A00E0557D /* SwiftyExpat */ = {
isa = PBXGroup;
children = (
E8C667EB19757405004EFA0C /* Expat.swift */,
E8FB779D1971E5AA00E0557D /* main.swift */,
E8FB77431971609A00E0557D /* SwiftyExpat.h */,
E8FB775E1971667F00E0557D /* expat */,
@ -341,6 +344,7 @@
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 */,
);
runOnlyForDeploymentPostprocessing = 0;

80
SwiftyExpat/Expat.swift Normal file
View File

@ -0,0 +1,80 @@
//
// Expat.swift
// SwiftyExpat
//
// Created by Helge Heß on 7/15/14.
// Copyright (c) 2014 Always Right Institute. All rights reserved.
//
/**
* Simple wrapper for the Expat parser. Though the block based Expat is
* reasonably easy to use as-is.
*
* Done as a class as this is no value object (and struct's have no deinit())
*/
class Expat : OutputStream {
let parser : XML_Parser
init(encoding: String = "UTF-8", nsSeparator: Character = ":") {
let sepUTF8 = ("" + nsSeparator).utf8
let separator = sepUTF8[sepUTF8.startIndex]
var newParser : XML_Parser = nil
encoding.withCString { cs in
// if I use parser, swiftc crashes (if Expat is a class)
// FIXME: use String for separator, and codepoints to get the Int?
newParser = XML_ParserCreateNS(cs, 58 /* ':' */)
}
assert(newParser != nil)
parser = newParser
}
deinit {
XML_ParserFree(parser)
}
/* feed the parser */
func write(cs: CString) {
let cslen = strlen(cs)
let isFinal = cslen == 0
XML_Parse(parser, cs, Int32(cslen), isFinal ? 1 : 0)
}
func write(s: String) {
s.withCString { cs in self.write(cs) }
}
func close() {
}
/* callbacks */
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
let sName = String.fromCString(name)! // unwrap, must be set
var sAttrs = [ String : String]()
if attrs != nil {
var i = 0
while attrs[i] { // Note: you cannot compare it with nil?!
let name = String.fromCString(attrs[i])
let value = String.fromCString(attrs[i + 1])
sAttrs[name!] = value! // force unwrap
i += 2
}
}
cb(sName, sAttrs)
}
return self
}
}

View File

@ -1133,6 +1133,11 @@ destroyBindings(BINDING *bindings, XML_Parser parser)
void XMLCALL
XML_ParserFree(XML_Parser parser)
{
TAG *tagList;
OPEN_INTERNAL_ENTITY *entityList;
if (parser == NULL)
return;
#ifdef EXPAT_WITH_BLOCKS
// Block_release seems to check for NULL
Block_release(startElementHandler);
@ -1159,10 +1164,6 @@ XML_ParserFree(XML_Parser parser)
Block_release(xmlDeclHandler);
#endif
TAG *tagList;
OPEN_INTERNAL_ENTITY *entityList;
if (parser == NULL)
return;
/* free tagStack and freeTagList */
tagList = tagStack;
for (;;) {

View File

@ -8,63 +8,6 @@
import Foundation
struct Expat : OutputStream {
let parser : XML_Parser
init(encoding: String = "UTF-8", nsSeparator: Character = ":") {
let sepUTF8 = ("" + nsSeparator).utf8
let separator = sepUTF8[sepUTF8.startIndex]
var newParser : XML_Parser = nil
encoding.withCString { cs in
// if I use parser, swiftc crashes (if Expat is a class)
// FIXME: use String for separator, and codepoints to get the Int?
newParser = XML_ParserCreateNS(cs, 58 /* ':' */)
}
assert(newParser != nil)
parser = newParser
}
/* feed the parser */
func write(cs: CString) {
let cslen = strlen(cs)
let isFinal = cslen == 0
XML_Parse(parser, cs, Int32(cslen), isFinal ? 1 : 0)
}
func write(s: String) {
s.withCString { cs in self.write(cs) }
}
/* callbacks */
func onStartElement(cb: ( String, [ String : String ] ) -> Void) {
XML_SetStartElementHandler(parser, {
// void *userData, const XML_Char *name, const XML_Char **atts
( userData, name, attrs ) in
let sName = String.fromCString(name)! // unwrap, must be set
var sAttrs = [ String : String]()
if attrs != nil {
var i = 0
while attrs[i] { // Note: you cannot compare it with nil?!
let name = String.fromCString(attrs[i])
let value = String.fromCString(attrs[i + 1])
sAttrs[name!] = value! // force unwrap
i += 2
}
}
cb(sName, sAttrs)
})
}
}
func testit() {
println("testing it ...")