Updates delta cores + replaces ZipZap with ZIPFoundation
Replaces ZipZap with ZIPFoundation due to DeltaCore now using ZIPFoundation
This commit is contained in:
parent
f293a2843f
commit
15b23c13e7
@ -1 +1 @@
|
|||||||
Subproject commit 4947d10713ba31017e40df275f40a315cf0da897
|
Subproject commit ec24fdbd721a8a21636916797f65c2a97f1b0ac5
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 54d064d34a4d856fd34a49308f42f1aefac8eaad
|
Subproject commit f958a29481557135ffaf3d7f4c50b43edacffb7e
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit 9c295a2a287821544fec4b29d2b3f1205f965275
|
Subproject commit 1a45f455c2fb89a81fad1eea4abb198084a4e41a
|
||||||
@ -1 +1 @@
|
|||||||
Subproject commit a3f0547bc57c14b548105020136a9ead56f73470
|
Subproject commit 4641bfc256383817cbded045eaf214aacea6ac6d
|
||||||
@ -85,8 +85,6 @@
|
|||||||
BF6BF3271EB87EB8008E83CD /* PhotoLibraryImportOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6BF3261EB87EB8008E83CD /* PhotoLibraryImportOption.swift */; };
|
BF6BF3271EB87EB8008E83CD /* PhotoLibraryImportOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6BF3261EB87EB8008E83CD /* PhotoLibraryImportOption.swift */; };
|
||||||
BF6EE5E91F7C5F860051AD6C /* _GameControllerInputMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6EE5E81F7C5F860051AD6C /* _GameControllerInputMapping.swift */; };
|
BF6EE5E91F7C5F860051AD6C /* _GameControllerInputMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6EE5E81F7C5F860051AD6C /* _GameControllerInputMapping.swift */; };
|
||||||
BF6EE5EB1F7C5F8F0051AD6C /* GameControllerInputMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6EE5EA1F7C5F8F0051AD6C /* GameControllerInputMapping.swift */; };
|
BF6EE5EB1F7C5F8F0051AD6C /* GameControllerInputMapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6EE5EA1F7C5F8F0051AD6C /* GameControllerInputMapping.swift */; };
|
||||||
BF70798C1B6B464B0019077C /* ZipZap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; };
|
|
||||||
BF70798D1B6B464B0019077C /* ZipZap.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF70798B1B6B464B0019077C /* ZipZap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
|
||||||
BF71CF871FE90006001F1613 /* AppIconShortcutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF71CF861FE90006001F1613 /* AppIconShortcutsViewController.swift */; };
|
BF71CF871FE90006001F1613 /* AppIconShortcutsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF71CF861FE90006001F1613 /* AppIconShortcutsViewController.swift */; };
|
||||||
BF71CF8A1FE904B1001F1613 /* GameTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF71CF891FE904B1001F1613 /* GameTableViewCell.xib */; };
|
BF71CF8A1FE904B1001F1613 /* GameTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BF71CF891FE904B1001F1613 /* GameTableViewCell.xib */; };
|
||||||
BF797A2D1C2D339F00F1A000 /* UILabel+FontSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF797A2C1C2D339F00F1A000 /* UILabel+FontSize.swift */; };
|
BF797A2D1C2D339F00F1A000 /* UILabel+FontSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF797A2C1C2D339F00F1A000 /* UILabel+FontSize.swift */; };
|
||||||
@ -118,7 +116,6 @@
|
|||||||
BFF0742C1E9DC17500ACDF4A /* GBCDeltaCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */; };
|
BFF0742C1E9DC17500ACDF4A /* GBCDeltaCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */; };
|
||||||
BFF0742D1E9DC17500ACDF4A /* GBCDeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
BFF0742D1E9DC17500ACDF4A /* GBCDeltaCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
BFF6452E1F7CC5060056533E /* GameControllerInputMappingTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6B82A41F7CC2A300042BFB /* GameControllerInputMappingTransformer.swift */; };
|
BFF6452E1F7CC5060056533E /* GameControllerInputMappingTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF6B82A41F7CC2A300042BFB /* GameControllerInputMappingTransformer.swift */; };
|
||||||
BFF93AA01E0FB036005EC865 /* InputStreamOutputWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */; };
|
|
||||||
BFFA4C091E8A24D600D87934 /* GameTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA4C081E8A24D600D87934 /* GameTableViewCell.swift */; };
|
BFFA4C091E8A24D600D87934 /* GameTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA4C081E8A24D600D87934 /* GameTableViewCell.swift */; };
|
||||||
BFFA71DD1AAC406100EE9DD1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */; };
|
BFFA71DD1AAC406100EE9DD1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFFA71DC1AAC406100EE9DD1 /* AppDelegate.swift */; };
|
||||||
BFFA71E21AAC406100EE9DD1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFFA71E01AAC406100EE9DD1 /* Main.storyboard */; };
|
BFFA71E21AAC406100EE9DD1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFFA71E01AAC406100EE9DD1 /* Main.storyboard */; };
|
||||||
@ -140,7 +137,6 @@
|
|||||||
BF9F4FD01AAD7B87004C9500 /* DeltaCore.framework in Embed Frameworks */,
|
BF9F4FD01AAD7B87004C9500 /* DeltaCore.framework in Embed Frameworks */,
|
||||||
BFF0742D1E9DC17500ACDF4A /* GBCDeltaCore.framework in Embed Frameworks */,
|
BFF0742D1E9DC17500ACDF4A /* GBCDeltaCore.framework in Embed Frameworks */,
|
||||||
BFEC732E1AAECC4A00650035 /* Roxas.framework in Embed Frameworks */,
|
BFEC732E1AAECC4A00650035 /* Roxas.framework in Embed Frameworks */,
|
||||||
BF70798D1B6B464B0019077C /* ZipZap.framework in Embed Frameworks */,
|
|
||||||
BF0418151D01E93400E85BCF /* GBADeltaCore.framework in Embed Frameworks */,
|
BF0418151D01E93400E85BCF /* GBADeltaCore.framework in Embed Frameworks */,
|
||||||
BF99C6951D0A9AA600BA92BC /* SNESDeltaCore.framework in Embed Frameworks */,
|
BF99C6951D0A9AA600BA92BC /* SNESDeltaCore.framework in Embed Frameworks */,
|
||||||
);
|
);
|
||||||
@ -250,7 +246,6 @@
|
|||||||
BFEC732C1AAECC4A00650035 /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BFEC732C1AAECC4A00650035 /* Roxas.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BFEF24F21F7DD4FB00454C62 /* SaveStateMigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveStateMigrationPolicy.swift; sourceTree = "<group>"; };
|
BFEF24F21F7DD4FB00454C62 /* SaveStateMigrationPolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveStateMigrationPolicy.swift; sourceTree = "<group>"; };
|
||||||
BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GBCDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
BFF0742B1E9DC17500ACDF4A /* GBCDeltaCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = GBCDeltaCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputStreamOutputWriter.swift; sourceTree = "<group>"; };
|
|
||||||
BFFA4C081E8A24D600D87934 /* GameTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameTableViewCell.swift; sourceTree = "<group>"; };
|
BFFA4C081E8A24D600D87934 /* GameTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
BFFA71D71AAC406100EE9DD1 /* Delta.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Delta.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
BFFA71D71AAC406100EE9DD1 /* Delta.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Delta.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BFFA71DB1AAC406100EE9DD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
BFFA71DB1AAC406100EE9DD1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
@ -273,7 +268,6 @@
|
|||||||
BF9F4FCF1AAD7B87004C9500 /* DeltaCore.framework in Frameworks */,
|
BF9F4FCF1AAD7B87004C9500 /* DeltaCore.framework in Frameworks */,
|
||||||
BFEC732D1AAECC4A00650035 /* Roxas.framework in Frameworks */,
|
BFEC732D1AAECC4A00650035 /* Roxas.framework in Frameworks */,
|
||||||
BF99C6941D0A9AA600BA92BC /* SNESDeltaCore.framework in Frameworks */,
|
BF99C6941D0A9AA600BA92BC /* SNESDeltaCore.framework in Frameworks */,
|
||||||
BF70798C1B6B464B0019077C /* ZipZap.framework in Frameworks */,
|
|
||||||
BF0418141D01E93400E85BCF /* GBADeltaCore.framework in Frameworks */,
|
BF0418141D01E93400E85BCF /* GBADeltaCore.framework in Frameworks */,
|
||||||
BFF0742C1E9DC17500ACDF4A /* GBCDeltaCore.framework in Frameworks */,
|
BFF0742C1E9DC17500ACDF4A /* GBCDeltaCore.framework in Frameworks */,
|
||||||
4FE8465FD28810191C3E5212 /* Pods_Delta.framework in Frameworks */,
|
4FE8465FD28810191C3E5212 /* Pods_Delta.framework in Frameworks */,
|
||||||
@ -394,7 +388,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
BF59426D1E09BC5D0051894B /* DatabaseManager.swift */,
|
BF59426D1E09BC5D0051894B /* DatabaseManager.swift */,
|
||||||
BFF93A9F1E0FB036005EC865 /* InputStreamOutputWriter.swift */,
|
|
||||||
BF5942711E09BC690051894B /* Model */,
|
BF5942711E09BC690051894B /* Model */,
|
||||||
BF95E2751E49763D0030E7AD /* OpenVGDB */,
|
BF95E2751E49763D0030E7AD /* OpenVGDB */,
|
||||||
);
|
);
|
||||||
@ -968,7 +961,6 @@
|
|||||||
BF696B801D9B2B02009639E0 /* Theme.swift in Sources */,
|
BF696B801D9B2B02009639E0 /* Theme.swift in Sources */,
|
||||||
BF7AE8081C2E858400B1B5BC /* GridMenuViewController.swift in Sources */,
|
BF7AE8081C2E858400B1B5BC /* GridMenuViewController.swift in Sources */,
|
||||||
BF6BF31A1EB82146008E83CD /* ClipboardImportOption.swift in Sources */,
|
BF6BF31A1EB82146008E83CD /* ClipboardImportOption.swift in Sources */,
|
||||||
BFF93AA01E0FB036005EC865 /* InputStreamOutputWriter.swift in Sources */,
|
|
||||||
BF59427F1E09BC830051894B /* GameCollection.swift in Sources */,
|
BF59427F1E09BC830051894B /* GameCollection.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import CoreData
|
|||||||
|
|
||||||
// Workspace
|
// Workspace
|
||||||
import DeltaCore
|
import DeltaCore
|
||||||
import ZipZap
|
import ZIPFoundation
|
||||||
|
|
||||||
// Pods
|
// Pods
|
||||||
import FileMD5Hash
|
import FileMD5Hash
|
||||||
@ -346,7 +346,6 @@ extension DatabaseManager
|
|||||||
{
|
{
|
||||||
DispatchQueue.global().async {
|
DispatchQueue.global().async {
|
||||||
|
|
||||||
var semaphores = Set<DispatchSemaphore>()
|
|
||||||
var outputURLs = Set<URL>()
|
var outputURLs = Set<URL>()
|
||||||
var errors = Set<ImportError>()
|
var errors = Set<ImportError>()
|
||||||
|
|
||||||
@ -354,16 +353,19 @@ extension DatabaseManager
|
|||||||
{
|
{
|
||||||
var archiveContainsValidGameFile = false
|
var archiveContainsValidGameFile = false
|
||||||
|
|
||||||
|
guard let archive = Archive(url: url, accessMode: .read) else {
|
||||||
|
errors.insert(.invalid(url))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry in archive
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
|
||||||
let archive = try ZZArchive(url: url)
|
|
||||||
|
|
||||||
for entry in archive.entries
|
|
||||||
{
|
{
|
||||||
// Ensure entry is not in a subdirectory
|
// Ensure entry is not in a subdirectory
|
||||||
guard !entry.fileName.contains("/") else { continue }
|
guard !entry.path.contains("/") else { continue }
|
||||||
|
|
||||||
let fileExtension = (entry.fileName as NSString).pathExtension
|
let fileExtension = (entry.path as NSString).pathExtension
|
||||||
|
|
||||||
guard GameType(fileExtension: fileExtension) != nil else { continue }
|
guard GameType(fileExtension: fileExtension) != nil else { continue }
|
||||||
|
|
||||||
@ -372,55 +374,23 @@ extension DatabaseManager
|
|||||||
// However, if this game file does turn out to be invalid when extracting, we'll return an ImportError.invalid error specific to this game file
|
// However, if this game file does turn out to be invalid when extracting, we'll return an ImportError.invalid error specific to this game file
|
||||||
archiveContainsValidGameFile = true
|
archiveContainsValidGameFile = true
|
||||||
|
|
||||||
// ROMs may potentially be very large, so we extract using file streams and not raw Data
|
|
||||||
let inputStream = try entry.newStream()
|
|
||||||
|
|
||||||
// Must use temporary directory, and not the directory containing zip file, since the latter might be read-only (such as when importing from Safari)
|
// Must use temporary directory, and not the directory containing zip file, since the latter might be read-only (such as when importing from Safari)
|
||||||
let outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(entry.fileName)
|
let outputURL = FileManager.default.temporaryDirectory.appendingPathComponent(entry.path)
|
||||||
|
|
||||||
if FileManager.default.fileExists(atPath: outputURL.path)
|
if FileManager.default.fileExists(atPath: outputURL.path)
|
||||||
{
|
{
|
||||||
try FileManager.default.removeItem(at: outputURL)
|
try FileManager.default.removeItem(at: outputURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let outputStream = OutputStream(url: outputURL, append: false) else { continue }
|
_ = try archive.extract(entry, to: outputURL)
|
||||||
|
|
||||||
let semaphore = DispatchSemaphore(value: 0)
|
|
||||||
semaphores.insert(semaphore)
|
|
||||||
|
|
||||||
let outputWriter = InputStreamOutputWriter(inputStream: inputStream, outputStream: outputStream)
|
|
||||||
outputWriter.start { (error) in
|
|
||||||
if let error = error
|
|
||||||
{
|
|
||||||
if FileManager.default.fileExists(atPath: outputURL.path)
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
try FileManager.default.removeItem(at: outputURL)
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
print(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
print(error)
|
|
||||||
|
|
||||||
errors.insert(.invalid(outputURL))
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
outputURLs.insert(outputURL)
|
outputURLs.insert(outputURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
semaphore.signal()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
print(error)
|
print(error)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !archiveContainsValidGameFile
|
if !archiveContainsValidGameFile
|
||||||
{
|
{
|
||||||
@ -428,11 +398,6 @@ extension DatabaseManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for semaphore in semaphores
|
|
||||||
{
|
|
||||||
semaphore.wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
for url in urls
|
for url in urls
|
||||||
{
|
{
|
||||||
if FileManager.default.fileExists(atPath: url.path)
|
if FileManager.default.fileExists(atPath: url.path)
|
||||||
|
|||||||
@ -1,148 +0,0 @@
|
|||||||
//
|
|
||||||
// InputStreamOutputWriter.swift
|
|
||||||
// Delta
|
|
||||||
//
|
|
||||||
// Created by Riley Testut on 12/25/16.
|
|
||||||
// Copyright © 2016 Riley Testut. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
private let MaximumBufferLength = 4 * 1024 // 4 KB
|
|
||||||
|
|
||||||
class InputStreamOutputWriter: NSObject
|
|
||||||
{
|
|
||||||
let inputStream: InputStream
|
|
||||||
let outputStream: OutputStream
|
|
||||||
|
|
||||||
private var completion: ((Error?) -> Void)?
|
|
||||||
|
|
||||||
private var dataBuffer = Data(capacity: MaximumBufferLength * 2)
|
|
||||||
|
|
||||||
init(inputStream: InputStream, outputStream: OutputStream)
|
|
||||||
{
|
|
||||||
self.inputStream = inputStream
|
|
||||||
self.outputStream = outputStream
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.inputStream.delegate = self
|
|
||||||
self.outputStream.delegate = self
|
|
||||||
}
|
|
||||||
|
|
||||||
func start(with completion: @escaping ((Error?) -> Void))
|
|
||||||
{
|
|
||||||
guard self.completion == nil else { return }
|
|
||||||
|
|
||||||
self.completion = completion
|
|
||||||
|
|
||||||
let writingQueue = DispatchQueue(label: "com.rileytestut.InputStreamOutputWriter.writingQueue", qos: .userInitiated)
|
|
||||||
writingQueue.async {
|
|
||||||
self.inputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
|
|
||||||
self.outputStream.schedule(in: .current, forMode: .defaultRunLoopMode)
|
|
||||||
|
|
||||||
self.outputStream.open()
|
|
||||||
self.inputStream.open()
|
|
||||||
|
|
||||||
RunLoop.current.run()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension InputStreamOutputWriter
|
|
||||||
{
|
|
||||||
func writeDataBuffer()
|
|
||||||
{
|
|
||||||
while self.outputStream.hasSpaceAvailable && self.dataBuffer.count > 0
|
|
||||||
{
|
|
||||||
self.dataBuffer.withUnsafeMutableBytes { (buffer: UnsafeMutablePointer<UInt8>) -> Void in
|
|
||||||
let writtenBytesCount = self.outputStream.write(buffer, maxLength: self.dataBuffer.count)
|
|
||||||
if writtenBytesCount >= 0
|
|
||||||
{
|
|
||||||
self.dataBuffer.removeSubrange(0 ..< writtenBytesCount)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func finishWriting()
|
|
||||||
{
|
|
||||||
self.inputStream.close()
|
|
||||||
self.outputStream.close()
|
|
||||||
|
|
||||||
self.inputStream.remove(from: .current, forMode: .commonModes)
|
|
||||||
self.outputStream.remove(from: .current, forMode: .commonModes)
|
|
||||||
|
|
||||||
self.completion?(self.inputStream.streamError ?? self.outputStream.streamError)
|
|
||||||
|
|
||||||
CFRunLoopStop(CFRunLoopGetCurrent())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension InputStreamOutputWriter: StreamDelegate
|
|
||||||
{
|
|
||||||
func stream(_ aStream: Stream, handle eventCode: Stream.Event)
|
|
||||||
{
|
|
||||||
if let inputStream = aStream as? InputStream
|
|
||||||
{
|
|
||||||
self.inputStream(inputStream, handle: eventCode)
|
|
||||||
}
|
|
||||||
else if let outputStream = aStream as? OutputStream
|
|
||||||
{
|
|
||||||
self.outputStream(outputStream, handle: eventCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func inputStream(_ inputStream: InputStream, handle eventCode: Stream.Event)
|
|
||||||
{
|
|
||||||
switch eventCode
|
|
||||||
{
|
|
||||||
case Stream.Event.hasBytesAvailable:
|
|
||||||
|
|
||||||
guard inputStream.streamError == nil else { return }
|
|
||||||
|
|
||||||
while inputStream.hasBytesAvailable
|
|
||||||
{
|
|
||||||
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: MaximumBufferLength)
|
|
||||||
|
|
||||||
let readBytesCount = inputStream.read(buffer, maxLength: MaximumBufferLength)
|
|
||||||
|
|
||||||
guard readBytesCount >= 0 else { break }
|
|
||||||
|
|
||||||
self.dataBuffer.append(buffer, count: readBytesCount)
|
|
||||||
|
|
||||||
buffer.deallocate(capacity: MaximumBufferLength)
|
|
||||||
|
|
||||||
self.writeDataBuffer()
|
|
||||||
}
|
|
||||||
|
|
||||||
case Stream.Event.endEncountered:
|
|
||||||
if self.dataBuffer.count == 0
|
|
||||||
{
|
|
||||||
self.finishWriting()
|
|
||||||
}
|
|
||||||
|
|
||||||
case Stream.Event.errorOccurred: self.finishWriting()
|
|
||||||
|
|
||||||
default: break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func outputStream(_ outputStream: OutputStream, handle eventCode: Stream.Event)
|
|
||||||
{
|
|
||||||
switch eventCode
|
|
||||||
{
|
|
||||||
case Stream.Event.hasSpaceAvailable:
|
|
||||||
self.writeDataBuffer()
|
|
||||||
|
|
||||||
if self.inputStream.streamStatus == .atEnd
|
|
||||||
{
|
|
||||||
self.finishWriting()
|
|
||||||
}
|
|
||||||
|
|
||||||
case Stream.Event.errorOccurred: self.finishWriting()
|
|
||||||
|
|
||||||
default: break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user