From 13b5d943d41f5000ed280985c34771607d896183 Mon Sep 17 00:00:00 2001 From: Jeff L <51171427+LebJe@users.noreply.github.com> Date: Sun, 2 May 2021 16:31:57 -0400 Subject: [PATCH] Improve Foundationless (#4) - Added three new options to Foundationless. - Added support for changing the amount of characters/bytes printed, whether to print in binary of hexadecimal, and changing the line width in Foundationless. * Use Swift 5.4 on Windows CI --- .github/workflows/buildAndTest.yml | 4 +- CHANGELOG.md | 5 + .../Sources/Foundationless/main.swift | 163 +++++++++++++++--- Sources/ArArchiveKit/ArArchiveReader.swift | 1 - 4 files changed, 143 insertions(+), 30 deletions(-) diff --git a/.github/workflows/buildAndTest.yml b/.github/workflows/buildAndTest.yml index 5a9e5af..ee09227 100644 --- a/.github/workflows/buildAndTest.yml +++ b/.github/workflows/buildAndTest.yml @@ -44,8 +44,8 @@ jobs: steps: - uses: actions/checkout@v2 - uses: seanmiddleditch/gha-setup-vsdevenv@master - - name: Install swift-DEVELOPMENT-SNAPSHOT-2021-01-27-a - run: Install-Binary -Url "https://swift.org/builds/development/windows10/swift-DEVELOPMENT-SNAPSHOT-2021-01-27-a/swift-DEVELOPMENT-SNAPSHOT-2021-01-27-a-windows10.exe" -Name "installer.exe" -ArgumentList ("-q") + - name: Install swift-5.4-RELEASE + run: Install-Binary -Url "https://swift.org/builds/swift-5.4-release/windows10/swift-5.4-RELEASE/swift-5.4-RELEASE-windows10.exe" -Name "installer.exe" -ArgumentList ("-q") - name: Set Environment Variables run: | echo "SDKROOT=C:\Library\Developer\Platforms\Windows.platform\Developer\SDKs\Windows.sdk" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append diff --git a/CHANGELOG.md b/CHANGELOG.md index c5d1a84..2bf234c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased]() +### Added + +- Added three new options to Foundationless. +- Added support for changing the amount of characters/bytes printed, whether to print in binary of hexadecimal, and changing the line width in Foundationless. + ### Fixed - Fixed a bug that occurred when parsing a file in an archive that contained a `\n` after it's content. diff --git a/Examples/Foundationless/Sources/Foundationless/main.swift b/Examples/Foundationless/Sources/Foundationless/main.swift index 1524a72..1ba75f4 100644 --- a/Examples/Foundationless/Sources/Foundationless/main.swift +++ b/Examples/Foundationless/Sources/Foundationless/main.swift @@ -14,6 +14,43 @@ import ArArchiveKit +// MARK: - Extensions + +// From: https://www.hackingwithswift.com/example-code/language/how-to-split-an-array-into-chunks +extension Array { + func chunked(into size: Int) -> [[Element]] { + stride(from: 0, to: self.count, by: size).map { + Array(self[$0.. Bool { switch s { case "-h": return true @@ -33,15 +70,22 @@ Reads the archive at `file` prints information about each file in the archive. -h, --help, -? Prints this message. -p Print the contents of the files in the archive. -b Print the binary representation of the files in the archive. -""" +USAGE: \(CommandLine.arguments[0]) [--help, -h, -?] [-p] [-b] [-w ] [-a ] -var shouldPrintFile = false -var printInBinary = false +Reads the archive at `file` and prints information about each file in the archive. + +-h, --help, -? Prints this message. +-p Print the contents of the files in the archive. +-b Print the binary representation of the files in the archive. +-w (defalut: \(width)) The amount of characters shown horizontally when printing the contents of a file in binary or ASCII/Unicode. +-a (default: \(amountOfBytes)) The amount of characters/bytes you want print from each file in the archive. Use \"-1\" (with the quotes) to print the full file. If the number is greater than the amount of bytes in the file, then it will equal the amount of bytes in the file. +-f (default: \(format.rawValue)) The format you want the file to be printed in. you can choose either \(Format.binary.rawValue) or \(Format.hexadecimal.rawValue). +""" func parseArgs() { if CommandLine.arguments.count < 2 || parseHelpFlag(CommandLine.arguments[1]) { print(usage) - exit(1) + exit(0) } if CommandLine.arguments.firstIndex(of: "-p") != nil { @@ -51,45 +95,110 @@ func parseArgs() { if CommandLine.arguments.firstIndex(of: "-b") != nil { printInBinary = true } + + if let index = CommandLine.arguments.firstIndex(of: "-w") { + if let w = Int(CommandLine.arguments[index + 1]) { + width = w + } else { + print("\"\(CommandLine.arguments[index + 1])\" is not valid value for -w.") + exit(ExitCode.invalidArgument.rawValue) + } + } + + if let index = CommandLine.arguments.firstIndex(of: "-a") { + if let a = Int(CommandLine.arguments[index + 1]) { + amountOfBytes = a + } else { + print("\"\(CommandLine.arguments[index + 1])\" is not valid value for -a.") + exit(ExitCode.invalidArgument.rawValue) + } + } + + if let index = CommandLine.arguments.firstIndex(of: "-f") { + if let f = Format(rawValue: CommandLine.arguments[index + 1]) { + format = f + } else { + print("\"\(CommandLine.arguments[index + 1])\" is not valid value for -f.") + exit(ExitCode.invalidArgument.rawValue) + } + } } parseArgs() -let fd = open(CommandLine.arguments[1], O_RDONLY) +// MARK: - Main Code + +func printContents(from bytes: [UInt8]) { + if printInBinary { + bytes + .chunked(into: width) + .forEach({ + $0.forEach({ byte in + switch format { + case .binary: + print(String(byte, radix: 2), terminator: " ") + case .hexadecimal: + print("0x\(String(byte, radix: 16))", terminator: " ") + } + }) + + print() + }) + } else { + print(String(bytes)) + } +} -let size = Int(lseek(fd, 0, SEEK_END)) +func main() throws { + let fd = open(CommandLine.arguments[1], O_RDONLY) -lseek(fd, 0, SEEK_SET) + let size = Int(lseek(fd, 0, SEEK_END)) -let buf = UnsafeMutableRawBufferPointer.allocate(byteCount: size, alignment: MemoryLayout.alignment) + lseek(fd, 0, SEEK_SET) -read(fd, buf.baseAddress, buf.count) + let buf = UnsafeMutableRawBufferPointer.allocate(byteCount: size, alignment: MemoryLayout.alignment) -let bufferPointer = buf.bindMemory(to: UInt8.self) + read(fd, buf.baseAddress, buf.count) -let bytes = Array(bufferPointer) + let bufferPointer = buf.bindMemory(to: UInt8.self) -let reader = try ArArchiveReader(archive: bytes) + let bytes = Array(bufferPointer) -for (header, file) in reader { - print("---------------------------") + let reader = try ArArchiveReader(archive: bytes) - print("Name: " + header.name) - print("User ID: " + String(header.userID)) - print("Group ID: " + String(header.groupID)) - print("Mode (In Octal): " + String(header.mode, radix: 8)) - print("File Size: " + String(header.size)) - print("File Modification Time: " + String(header.modificationTime)) + for (header, file) in reader { + print("---------------------------") - if shouldPrintFile { - print("Contents:\n") + print("Name: " + header.name) + print("User ID: " + String(header.userID)) + print("Group ID: " + String(header.groupID)) + print("Mode (In Octal): " + String(header.mode, radix: 8)) + print("File Size: " + String(header.size)) + print("File Modification Time: " + String(header.modificationTime)) - if printInBinary { - file.forEach({ print($0) }) - } else { - print(String(file)) + if shouldPrintFile { + print("Contents:\n") + if amountOfBytes != -1 { + amountOfBytes = amountOfBytes > file.count ? file.count : amountOfBytes + printContents(from: Array(file[0..