import Foundation // MARK: - Public extension String { /// Returns the receiver, quoted for safe insertion as an identifier in an /// SQL query. /// /// db.execute(sql: "SELECT * FROM \(tableName.quotedDatabaseIdentifier)") public var quotedDatabaseIdentifier: String { // See return "\"\(self)\"" } } /// Return as many question marks separated with commas as the *count* argument. /// /// databaseQuestionMarks(count: 3) // "?,?,?" public func databaseQuestionMarks(count: Int) -> String { repeatElement("?", count: count).joined(separator: ",") } // MARK: - Internal /// Reserved for GRDB: do not use. @inline(__always) @inlinable func GRDBPrecondition( _ condition: @autoclosure() -> Bool, _ message: @autoclosure() -> String = "", file: StaticString = #file, line: UInt = #line) { // Custom precondition function which aims at solving // and // if !condition() { fatalError(message(), file: file, line: line) } } func fatalError(_ error: E) -> Never { try! { throw error }() } // Workaround Swift inconvenience around factory methods of non-final classes func cast(_ value: T) -> U? { value as? U } extension RangeReplaceableCollection { /// Removes the first object that matches *predicate*. mutating func removeFirst(where predicate: (Element) throws -> Bool) rethrows { if let index = try firstIndex(where: predicate) { remove(at: index) } } } extension Dictionary { /// Removes the first object that matches *predicate*. mutating func removeFirst(where predicate: (Element) throws -> Bool) rethrows { if let index = try firstIndex(where: predicate) { remove(at: index) } } } extension DispatchQueue { private static var mainKey: DispatchSpecificKey<()> = { let key = DispatchSpecificKey<()>() DispatchQueue.main.setSpecific(key: key, value: ()) return key }() static var isMain: Bool { DispatchQueue.getSpecific(key: mainKey) != nil } } extension Sequence { func countElements(where predicate: (Element) throws -> Bool) rethrows -> Int { var count = 0 for e in self where try predicate(e) { count += 1 } return count } } /// Makes sure the `finally` function is executed even if `execute` throws, and /// rethrows the eventual first thrown error. /// /// Usage: /// /// try setup() /// try throwingFirstError( /// execute: work, /// finally: cleanup) func throwingFirstError(execute: () throws -> T, finally: () throws -> Void) throws -> T { var result: T? var firstError: Error? do { result = try execute() } catch { firstError = error } do { try finally() } catch { if firstError == nil { firstError = error } } if let firstError { throw firstError } return result! } struct PrintOutputStream: TextOutputStream { func write(_ string: String) { Swift.print(string) } } /// Concatenates two functions func concat(_ rhs: (() -> Void)?, _ lhs: (() -> Void)?) -> (() -> Void)? { switch (rhs, lhs) { case let (rhs, nil): return rhs case let (nil, lhs): return lhs case let (rhs?, lhs?): return { rhs() lhs() } } } /// Concatenates two functions func concat(_ rhs: ((T) -> Void)?, _ lhs: ((T) -> Void)?) -> ((T) -> Void)? { switch (rhs, lhs) { case let (rhs, nil): return rhs case let (nil, lhs): return lhs case let (rhs?, lhs?): return { rhs($0) lhs($0) } } } extension NSLocking { func synchronized( _ message: @autoclosure () -> String = #function, _ block: () throws -> T) rethrows -> T { lock() defer { unlock() } return try block() } // // Verbose version which helps understanding locking bugs // func synchronized(_ message: @autoclosure () -> String = "", _ block: () throws -> T) rethrows -> T { // let queueName = String(validatingUTF8: __dispatch_queue_get_label(nil)) // print("\(queueName ?? "n/d"): \(message()) acquiring \(self)") // lock() // print("\(queueName ?? "n/d"): \(message()) acquired \(self)") // defer { // print("\(queueName ?? "n/d"): \(message()) releasing \(self)") // unlock() // print("\(queueName ?? "n/d"): \(message()) released \(self)") // } // return try block() // } /// Performs the side effect outside of the synchronized block. This allows /// avoiding deadlocks, when the side effect feedbacks. func synchronized( _ message: @autoclosure () -> String = #function, _ block: (inout (() -> Void)?) -> Void) { var sideEffect: (() -> Void)? synchronized(message()) { block(&sideEffect) } sideEffect?() } } #if !canImport(ObjectiveC) @inlinable func autoreleasepool(invoking body: () throws -> Result) rethrows -> Result { try body() } #endif