Update code to be Swift 4 compatible
... it should still work w/ Swift 2, but I suppose we can drop this eventually :-)
This commit is contained in:
parent
e00c5b7983
commit
bd881e297b
14
README.md
14
README.md
|
@ -1,9 +1,11 @@
|
|||
SwiftyExpat
|
||||
===========
|
||||
# SwiftyExpat
|
||||
|
||||
|
||||
Simple wrapper for the Expat XML parser.
|
||||
|
||||
###Targets
|
||||
### Targets
|
||||
|
||||
2018-04-27: Updated to use Swift 4.0.3 (aka Xcode 9.2).
|
||||
|
||||
Updated to use Swift v0.2b5 (aka Xcode 7b5).
|
||||
|
||||
|
@ -17,7 +19,7 @@ The project includes two targets:
|
|||
|
||||
I suggest you start by looking at the SwiftyExpatTests.
|
||||
|
||||
####SwiftyExpat
|
||||
#### SwiftyExpat
|
||||
|
||||
This is a tiny framework wth a small Swift class to make the API nicer.
|
||||
Though this is not really necessary - Expat is reasonably easy to use from
|
||||
|
@ -55,10 +57,10 @@ Note: The closures in the raw API cannot capture variables. If you need to pass
|
|||
around context (very likely ...), you need to fill the regular Expat 'user data'
|
||||
field (which the wrapper does, if you need an example).
|
||||
|
||||
####SwiftyExpatTests
|
||||
#### SwiftyExpatTests
|
||||
|
||||
Just a tiny demo on how to invoke the parser.
|
||||
|
||||
###Contact
|
||||
### Contact
|
||||
|
||||
[@helje5](http://twitter.com/helje5) | helge@alwaysrightinstitute.com
|
||||
|
|
|
@ -286,7 +286,7 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0700;
|
||||
LastUpgradeCheck = 0700;
|
||||
LastUpgradeCheck = 0920;
|
||||
ORGANIZATIONNAME = "Always Right Institute";
|
||||
TargetAttributes = {
|
||||
E8FB773D1971609A00E0557D = {
|
||||
|
@ -390,13 +390,21 @@
|
|||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
|
@ -405,6 +413,7 @@
|
|||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
|
@ -422,6 +431,7 @@
|
|||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 4.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -435,13 +445,21 @@
|
|||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
|
@ -450,6 +468,7 @@
|
|||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
|
@ -459,6 +478,8 @@
|
|||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 4.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
};
|
||||
|
@ -479,6 +500,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = "de.alwaysrightinstitute.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -497,6 +519,7 @@
|
|||
PRODUCT_BUNDLE_IDENTIFIER = "de.alwaysrightinstitute.${PRODUCT_NAME:rfc1034identifier}";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0700"
|
||||
LastUpgradeVersion = "0920"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
@ -26,6 +26,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
|
@ -55,6 +56,7 @@
|
|||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* p.write("<hello>world</hello>")
|
||||
* p.close()
|
||||
*/
|
||||
public final class Expat : OutputStreamType, BooleanType {
|
||||
public final class Expat {
|
||||
|
||||
public let nsSeparator : Character
|
||||
|
||||
|
@ -32,15 +32,20 @@ public final class Expat : OutputStreamType, BooleanType {
|
|||
let sepUTF8 = ("" + String(self.nsSeparator)).utf8
|
||||
let separator = sepUTF8[sepUTF8.startIndex]
|
||||
|
||||
parser = encoding.withCString { cs in
|
||||
let parser = 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?
|
||||
XML_ParserCreateNS(cs, XML_Char(separator))
|
||||
}
|
||||
assert(parser != nil)
|
||||
self.parser = parser
|
||||
|
||||
// TBD: what is the better way to do this?
|
||||
let ud = unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
|
||||
#if swift(>=4.0)
|
||||
let ud = unsafeBitCast(self, to: UnsafeMutableRawPointer.self)
|
||||
#else
|
||||
let ud = unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
|
||||
#endif
|
||||
XML_SetUserData(parser, ud)
|
||||
|
||||
registerCallbacks()
|
||||
|
@ -63,11 +68,15 @@ public final class Expat : OutputStreamType, BooleanType {
|
|||
/* feed the parser */
|
||||
|
||||
public func feedRaw
|
||||
(cs: UnsafePointer<CChar>, final: Bool = false) -> ExpatResult
|
||||
(_ cs: UnsafePointer<CChar>, final: Bool = false) -> ExpatResult
|
||||
{
|
||||
// v4: for some reason this accepts a 'String', but for such it doesn't
|
||||
// actually work
|
||||
let cslen = cs != nil ? strlen(cs) : 0 // cs? checks for a NULL C string
|
||||
#if swift(>=4.0)
|
||||
let cslen = strlen(cs) // cs? checks for a NULL C string
|
||||
#else
|
||||
let cslen = cs != nil ? strlen(cs) : 0 // cs? checks for a NULL C string
|
||||
#endif
|
||||
let isFinal : Int32 = final ? 1 : 0
|
||||
|
||||
//dumpCharBuf(cs, Int(cslen))
|
||||
|
@ -84,13 +93,13 @@ public final class Expat : OutputStreamType, BooleanType {
|
|||
return ExpatResult.Error(error)
|
||||
}
|
||||
}
|
||||
public func feed(s: String, final: Bool = false) -> ExpatResult {
|
||||
public func feed(_ s: String, final: Bool = false) -> ExpatResult {
|
||||
return s.withCString { cs -> ExpatResult in
|
||||
return self.feedRaw(cs, final: final)
|
||||
}
|
||||
}
|
||||
|
||||
public func write(s: String) {
|
||||
public func write(_ s: String) {
|
||||
let result = self.feed(s)
|
||||
|
||||
// doesn't work with associated value?: assert(ExpatResult.OK == result)
|
||||
|
@ -115,10 +124,16 @@ public final class Expat : OutputStreamType, BooleanType {
|
|||
|
||||
func registerCallbacks() {
|
||||
XML_SetStartElementHandler(parser) { ud, name, attrs in
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbStartElement else { return }
|
||||
#if swift(>=4.0)
|
||||
let me = unsafeBitCast(ud, to: Expat.self)
|
||||
guard let cb = me.cbStartElement else { return }
|
||||
let sName = name != nil ? String(cString: name!) : ""
|
||||
#else
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbStartElement else { return }
|
||||
let sName = String.fromCString(name)! // unwrap, must be set
|
||||
#endif
|
||||
|
||||
let sName = String.fromCString(name)! // unwrap, must be set
|
||||
|
||||
// FIXME: we should not copy stuff, but have a wrapper which works on the
|
||||
// attrs structure 'on demand'
|
||||
|
@ -127,27 +142,46 @@ public final class Expat : OutputStreamType, BooleanType {
|
|||
}
|
||||
|
||||
XML_SetEndElementHandler(parser) { ud, name in
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbEndElement else { return }
|
||||
|
||||
let sName = String.fromCString(name)! // unwrap, must be set
|
||||
cb(sName)
|
||||
#if swift(>=4.0)
|
||||
let me = unsafeBitCast(ud, to: Expat.self)
|
||||
guard let cb = me.cbEndElement else { return }
|
||||
let sName = String(cString: name!) // force unwrap, must be set
|
||||
cb(sName)
|
||||
#else
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbEndElement else { return }
|
||||
let sName = String.fromCString(name)! // force unwrap, must be set
|
||||
cb(sName)
|
||||
#endif
|
||||
}
|
||||
|
||||
XML_SetStartNamespaceDeclHandler(parser) { ud, prefix, uri in
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbStartNS else { return }
|
||||
|
||||
let sPrefix = String.fromCString(prefix)
|
||||
let sURI = String.fromCString(uri)!
|
||||
cb(sPrefix, sURI)
|
||||
#if swift(>=4.0)
|
||||
let me = unsafeBitCast(ud, to: Expat.self)
|
||||
guard let cb = me.cbStartNS else { return }
|
||||
let sPrefix = prefix != nil ? String(cString: prefix!) : nil
|
||||
let sURI = String(cString: uri!)
|
||||
cb(sPrefix, sURI)
|
||||
#else
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbStartNS else { return }
|
||||
let sPrefix = String.fromCString(prefix)
|
||||
let sURI = String.fromCString(uri)!
|
||||
cb(sPrefix, sURI)
|
||||
#endif
|
||||
}
|
||||
XML_SetEndNamespaceDeclHandler(parser) { ud, prefix in
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbEndNS else { return }
|
||||
|
||||
let sPrefix = String.fromCString(prefix)
|
||||
cb(sPrefix)
|
||||
#if swift(>=4.0)
|
||||
let me = unsafeBitCast(ud, to: Expat.self)
|
||||
guard let cb = me.cbEndNS else { return }
|
||||
let sPrefix = prefix != nil ? String(cString: prefix!) : nil
|
||||
cb(sPrefix)
|
||||
#else
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbEndNS else { return }
|
||||
let sPrefix = String.fromCString(prefix)
|
||||
cb(sPrefix)
|
||||
#endif
|
||||
}
|
||||
|
||||
XML_SetCharacterDataHandler(parser) { ud, cs, cslen in
|
||||
|
@ -156,16 +190,26 @@ public final class Expat : OutputStreamType, BooleanType {
|
|||
// println("CS: \(cs[0]) len \(cslen)")
|
||||
guard cslen > 0 else { return }
|
||||
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbCharacterData else { return }
|
||||
#if swift(>=4.0)
|
||||
let me = unsafeBitCast(ud, to: Expat.self)
|
||||
guard let cb = me.cbCharacterData else { return }
|
||||
|
||||
guard let s = String.fromCString(cs, length: Int(cslen)) else {
|
||||
print("ERROR: could not convert CString to String?! (len=\(cslen))")
|
||||
dumpCharBuf(cs, len: Int(cslen))
|
||||
return
|
||||
}
|
||||
let cs2 = UnsafeRawPointer(cs!).assumingMemoryBound(to: UInt8.self)
|
||||
let bp = UnsafeBufferPointer(start: cs2, count: Int(cslen))
|
||||
let s = String(decoding: bp, as: UTF8.self)
|
||||
cb(s)
|
||||
#else
|
||||
let me = unsafeBitCast(ud, Expat.self)
|
||||
guard let cb = me.cbCharacterData else { return }
|
||||
|
||||
cb(s)
|
||||
guard let s = String.fromCString(cs, length: Int(cslen)) else {
|
||||
print("ERROR: could not convert CString to String?! (len=\(cslen))")
|
||||
dumpCharBuf(cs, len: Int(cslen))
|
||||
return
|
||||
}
|
||||
|
||||
cb(s)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,33 +241,63 @@ public final class Expat : OutputStreamType, BooleanType {
|
|||
var cbCharacterData : CDataHandler?
|
||||
var cbError : ErrorHandler?
|
||||
|
||||
public func onStartElement(cb: StartElementHandler)-> Self {
|
||||
cbStartElement = cb
|
||||
return self
|
||||
}
|
||||
public func onEndElement(cb: EndElementHandler) -> Self {
|
||||
cbEndElement = cb
|
||||
return self
|
||||
}
|
||||
#if swift(>=3.0)
|
||||
public func onStartElement(cb: @escaping StartElementHandler)-> Self {
|
||||
cbStartElement = cb
|
||||
return self
|
||||
}
|
||||
public func onEndElement(cb: @escaping EndElementHandler) -> Self {
|
||||
cbEndElement = cb
|
||||
return self
|
||||
}
|
||||
|
||||
public func onStartNamespace(cb: StartNamespaceHandler) -> Self {
|
||||
cbStartNS = cb
|
||||
return self
|
||||
}
|
||||
public func onEndNamespace(cb: EndNamespaceHandler) -> Self {
|
||||
cbEndNS = cb
|
||||
return self
|
||||
}
|
||||
public func onStartNamespace(cb: @escaping StartNamespaceHandler) -> Self {
|
||||
cbStartNS = cb
|
||||
return self
|
||||
}
|
||||
public func onEndNamespace(cb: @escaping EndNamespaceHandler) -> Self {
|
||||
cbEndNS = cb
|
||||
return self
|
||||
}
|
||||
|
||||
public func onCharacterData(cb: CDataHandler) -> Self {
|
||||
cbCharacterData = cb
|
||||
return self
|
||||
}
|
||||
public func onCharacterData(cb: @escaping CDataHandler) -> Self {
|
||||
cbCharacterData = cb
|
||||
return self
|
||||
}
|
||||
|
||||
public func onError(cb: ErrorHandler) -> Self {
|
||||
cbError = cb
|
||||
return self
|
||||
}
|
||||
public func onError(cb: @escaping ErrorHandler) -> Self {
|
||||
cbError = cb
|
||||
return self
|
||||
}
|
||||
#else
|
||||
public func onStartElement(cb: StartElementHandler)-> Self {
|
||||
cbStartElement = cb
|
||||
return self
|
||||
}
|
||||
public func onEndElement(cb: EndElementHandler) -> Self {
|
||||
cbEndElement = cb
|
||||
return self
|
||||
}
|
||||
|
||||
public func onStartNamespace(cb: StartNamespaceHandler) -> Self {
|
||||
cbStartNS = cb
|
||||
return self
|
||||
}
|
||||
public func onEndNamespace(cb: EndNamespaceHandler) -> Self {
|
||||
cbEndNS = cb
|
||||
return self
|
||||
}
|
||||
|
||||
public func onCharacterData(cb: CDataHandler) -> Self {
|
||||
cbCharacterData = cb
|
||||
return self
|
||||
}
|
||||
|
||||
public func onError(cb: ErrorHandler) -> Self {
|
||||
cbError = cb
|
||||
return self
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -233,24 +307,44 @@ public extension Expat { // Namespaces
|
|||
( String, String, [String : String] ) -> Void
|
||||
public typealias EndElementNSHandler = ( String, String ) -> Void
|
||||
|
||||
public func onStartElementNS(cb: StartElementNSHandler) -> Self {
|
||||
let sep = self.nsSeparator // so that we don't capture 'self' (necessary?)
|
||||
return onStartElement {
|
||||
let comps = $0.characters.split(sep, maxSplit: 1, allowEmptySlices: false)
|
||||
.map { String($0) }
|
||||
cb(comps[0], comps[1], $1)
|
||||
#if swift(>=3.2)
|
||||
public func onStartElementNS(cb: @escaping StartElementNSHandler) -> Self {
|
||||
let sep = self.nsSeparator // so that we don't capture 'self' (necessary?)
|
||||
return onStartElement {
|
||||
// split(separator:maxSplits:omittingEmptySubsequences:)
|
||||
let comps = $0.split(separator: sep, maxSplits: 1,
|
||||
omittingEmptySubsequences: true)
|
||||
cb(String(comps[0]), String(comps[1]), $1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func onEndElementNS(cb: EndElementNSHandler) -> Self {
|
||||
let sep = self.nsSeparator // so that we don't capture 'self' (necessary?)
|
||||
return onEndElement {
|
||||
let comps = $0.characters.split(sep, maxSplit: 1, allowEmptySlices: false)
|
||||
.map { String($0) }
|
||||
cb(comps[0], comps[1])
|
||||
public func onEndElementNS(cb: @escaping EndElementNSHandler) -> Self {
|
||||
let sep = self.nsSeparator // so that we don't capture 'self' (necessary?)
|
||||
return onEndElement {
|
||||
let comps = $0.split(separator: sep, maxSplits: 1,
|
||||
omittingEmptySubsequences: true)
|
||||
cb(String(comps[0]), String(comps[1]))
|
||||
}
|
||||
}
|
||||
#else
|
||||
public func onStartElementNS(cb: StartElementNSHandler) -> Self {
|
||||
let sep = self.nsSeparator // so that we don't capture 'self' (necessary?)
|
||||
return onStartElement {
|
||||
let comps = $0.characters.split(sep, maxSplit: 1, allowEmptySlices: false)
|
||||
.map { String($0) }
|
||||
cb(comps[0], comps[1], $1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func onEndElementNS(cb: EndElementNSHandler) -> Self {
|
||||
let sep = self.nsSeparator // so that we don't capture 'self' (necessary?)
|
||||
return onEndElement {
|
||||
let comps = $0.characters.split(sep, maxSplit: 1, allowEmptySlices: false)
|
||||
.map { String($0) }
|
||||
cb(comps[0], comps[1])
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -275,7 +369,7 @@ extension XML_Error : CustomStringConvertible {
|
|||
}
|
||||
}
|
||||
|
||||
public enum ExpatResult : CustomStringConvertible, BooleanType {
|
||||
public enum ExpatResult : CustomStringConvertible {
|
||||
|
||||
case OK
|
||||
case Suspended
|
||||
|
@ -300,18 +394,41 @@ public enum ExpatResult : CustomStringConvertible, BooleanType {
|
|||
|
||||
/* debug */
|
||||
|
||||
func dumpCharBuf(buf: UnsafePointer<CChar>, len : Int) {
|
||||
func dumpCharBuf(_ buf: UnsafePointer<CChar>, len : Int) {
|
||||
print("*-- buffer (len=\(len))")
|
||||
for i in 0 ..< len {
|
||||
let cp = Int(buf[i])
|
||||
let c = Character(UnicodeScalar(cp))
|
||||
#if swift(>=3.0)
|
||||
let c = Character(UnicodeScalar(cp)!)
|
||||
#else
|
||||
let c = Character(UnicodeScalar(cp))
|
||||
#endif
|
||||
print(" [\(i)]: \(cp) \(c)")
|
||||
}
|
||||
print("---")
|
||||
}
|
||||
|
||||
#if swift(>=3.0)
|
||||
|
||||
func makeAttributesDictionary
|
||||
(attrs : UnsafeMutablePointer<UnsafePointer<XML_Char>>)
|
||||
(_ attrs : UnsafeMutablePointer<UnsafePointer<XML_Char>?>?)
|
||||
-> [ String : String ]
|
||||
{
|
||||
var sAttrs = [ String : String ]()
|
||||
guard let attrs = attrs else { return sAttrs }
|
||||
var i = 0
|
||||
while attrs[i] != nil {
|
||||
let name = String(cString: attrs[i]!)
|
||||
let value = attrs[i + 1] != nil ? String(cString: attrs[i + 1]!) : ""
|
||||
sAttrs[name] = value
|
||||
i += 2
|
||||
}
|
||||
return sAttrs
|
||||
}
|
||||
#else
|
||||
|
||||
func makeAttributesDictionary
|
||||
(_ attrs : UnsafeMutablePointer<UnsafePointer<XML_Char>>)
|
||||
-> [ String : String ]
|
||||
{
|
||||
var sAttrs = [ String : String ]()
|
||||
|
@ -326,3 +443,5 @@ func makeAttributesDictionary
|
|||
}
|
||||
return sAttrs
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
// Copyright (c) 2014 Always Right Institute. All rights reserved.
|
||||
//
|
||||
|
||||
#if swift(>=4.0)
|
||||
|
||||
#else
|
||||
|
||||
// Those are mostly dirty hacks to get what I need :-)
|
||||
// I would be very interested in better way to do those things, W/O using
|
||||
// Foundation.
|
||||
|
@ -36,3 +40,4 @@ extension String {
|
|||
}
|
||||
|
||||
}
|
||||
#endif // <Swift 4
|
||||
|
|
|
@ -20,9 +20,9 @@ class SwiftyExpatTests: XCTestCase {
|
|||
p = Expat()
|
||||
.onStartElement { name, attrs in print("<\(name) \(attrs)") }
|
||||
.onEndElement { name in print(">\(name)") }
|
||||
.onStartNamespace { prefix, uri in print("+NS[\(prefix)] = \(uri)") }
|
||||
.onEndNamespace { prefix in print("-NS[\(prefix)]") }
|
||||
.onCharacterData { content in print("TEXT: \(content)") }
|
||||
.onStartNamespace { prefix, uri in print("+NS[\(prefix ?? "")] = \(uri)")}
|
||||
.onEndNamespace { prefix in print("-NS[\(prefix ?? "")]") }
|
||||
.onCharacterData { content in print("TEXT: \(content ?? "")") }
|
||||
.onError { error in print("ERROR \(error)") }
|
||||
}
|
||||
|
||||
|
@ -38,11 +38,11 @@ class SwiftyExpatTests: XCTestCase {
|
|||
let testXML = "<hello xmlns='YoYo' a='5'><x>world</x></hello>"
|
||||
|
||||
result = p.feed(testXML)
|
||||
XCTAssert(result)
|
||||
XCTAssert(result.boolValue)
|
||||
|
||||
result = p.close() // EOF
|
||||
print("Feed result: \(result)")
|
||||
XCTAssert(result)
|
||||
XCTAssert(result.boolValue)
|
||||
}
|
||||
|
||||
func testErrorHandling() {
|
||||
|
@ -53,10 +53,10 @@ class SwiftyExpatTests: XCTestCase {
|
|||
|
||||
result = p.feed(testXML)
|
||||
print("Feed result: \(result)")
|
||||
XCTAssert(!result)
|
||||
XCTAssert(!result.boolValue)
|
||||
|
||||
result = p.close() // EOF
|
||||
XCTAssert(!result)
|
||||
XCTAssert(!result.boolValue)
|
||||
}
|
||||
|
||||
func testRawAPI() {
|
||||
|
@ -66,11 +66,19 @@ class SwiftyExpatTests: XCTestCase {
|
|||
defer { XML_ParserFree(p); }
|
||||
|
||||
XML_SetStartElementHandler(p) { _, name, attrs in
|
||||
let nameString = String.fromCString(name)!
|
||||
#if swift(>=3.0)
|
||||
let nameString = String(cString: name!)
|
||||
#else
|
||||
let nameString = String.fromCString(name)!
|
||||
#endif
|
||||
print("start tag \(nameString)")
|
||||
}
|
||||
XML_SetEndElementHandler (p) { _, name in
|
||||
let nameString = String.fromCString(name)!
|
||||
#if swift(>=3.0)
|
||||
let nameString = String(cString: name!)
|
||||
#else
|
||||
let nameString = String.fromCString(name)!
|
||||
#endif
|
||||
print("end tag \(nameString)")
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue