Created
June 25, 2015 17:14
-
-
Save listrophy/45b10cf2c958028ca57e to your computer and use it in GitHub Desktop.
Wrap glob(3) in Swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Glob.swift | |
// | |
// Created by Brad Grzesiak on 6/25/15. | |
// Copyright © 2015 Bendyworks Inc. | |
// Released under the Apache v2 License. | |
// | |
import Foundation | |
class Glob: CollectionType { | |
private var globFlags = GLOB_TILDE | GLOB_BRACE | GLOB_MARK | |
var paths = [String]() | |
var startIndex: Int { | |
return paths.startIndex | |
} | |
var endIndex: Int { | |
return paths.endIndex | |
} | |
subscript(i: Int) -> String { | |
return paths[i] | |
} | |
init(pattern: String) { | |
var gt = glob_t() | |
if let cPatt = cPattern(pattern) { | |
if executeGlob(cPatt, gt: >) { | |
populateFiles(gt) | |
} | |
} | |
globfree(>) | |
} | |
private | |
func executeGlob(pattern: [CChar], gt: UnsafeMutablePointer<glob_t>) -> Bool { | |
return 0 == glob(pattern, globFlags, nil, gt) | |
} | |
private | |
func cPattern(pattern: String) -> [CChar]? { | |
return pattern.cStringUsingEncoding(NSUTF8StringEncoding) | |
} | |
private func populateFiles(gt: glob_t) { | |
for var i = 0; i < Int(gt.gl_matchc); i++ { | |
if let path = String.fromCString(gt.gl_pathv[i]) { | |
paths.append(path) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// GlobTester.swift | |
// | |
// Created by Brad Grzesiak on 6/25/15. | |
// Copyright © 2015 Bendyworks Inc. | |
// Released under the Apache v2 License. | |
// | |
import XCTest | |
class GlobTester: XCTestCase { | |
let tmpFiles = ["foo", "bar", "baz"] | |
var tmpDir: String? | |
override func setUp() { | |
super.setUp() | |
var tmpDirTmpl = "/tmp/glob-test.XXXXX".cStringUsingEncoding(NSUTF8StringEncoding)! | |
self.tmpDir = String.fromCString(mkdtemp(&tmpDirTmpl)) | |
for file in tmpFiles { | |
close(open("\(tmpDir!)/\(file)", O_CREAT)) | |
} | |
} | |
override func tearDown() { | |
for file in tmpFiles { | |
unlink("\(tmpDir!)/\(file)") | |
} | |
rmdir(self.tmpDir!) | |
super.tearDown() | |
} | |
func testBraces() { | |
let pattern = "\(tmpDir!)/ba{r,y,z}" | |
let glob = Glob(pattern: pattern) | |
var contents = [String]() | |
for file in glob { | |
contents.append(file) | |
} | |
XCTAssertEqual(contents, ["\(tmpDir!)/bar", "\(tmpDir!)/baz"], "matching with braces failed") | |
} | |
func testNothingMatches() { | |
let pattern = "\(tmpDir!)/nothing" | |
let glob = Glob(pattern: pattern) | |
var contents = [String]() | |
for file in glob { | |
contents.append(file) | |
} | |
XCTAssertEqual(contents, [], "expected empty list of files") | |
} | |
func testDirectAccess() { | |
let pattern = "\(tmpDir!)/ba{r,y,z}" | |
let glob = Glob(pattern: pattern) | |
XCTAssertEqual(glob.paths, ["\(tmpDir!)/bar", "\(tmpDir!)/baz"], "matching with braces failed") | |
} | |
func testIterateTwice() { | |
let pattern = "\(tmpDir!)/ba{r,y,z}" | |
let glob = Glob(pattern: pattern) | |
var contents1 = [String]() | |
var contents2 = [String]() | |
for file in glob { | |
contents1.append(file) | |
} | |
let filesAfterOnce = glob.paths | |
for file in glob { | |
contents2.append(file) | |
} | |
XCTAssertEqual(contents1, contents2, "results for calling for-in twice are the same") | |
XCTAssertEqual(glob.paths, filesAfterOnce, "calling for-in twice doesn't only memoizes once") | |
} | |
func testIndexing() { | |
let pattern = "\(tmpDir!)/ba{r,y,z}" | |
let glob = Glob(pattern: pattern) | |
XCTAssertEqual(glob[0], "\(tmpDir!)/bar", "indexing") | |
} | |
} |
func cPattern(pattern: String) -> [CChar]? {
return pattern.cStringUsingEncoding(NSUTF8StringEncoding)
}
This is redundant, since Swift automatically converts strings into pointer to UTF8 buffers.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I forked and updated this gist. Please consider incorporating my suggestions:
Foundation
(which Linux won't have); replaced withDarwin
(You were mostly makingDarwin
calls anyway)I left the public API unchanged but I did not run any of your tests to ensure compatibility.