Skip to content

Instantly share code, notes, and snippets.

@EricRabil
Last active December 14, 2022 20:58
Show Gist options
  • Save EricRabil/8ddbd03f4a63315e3e40a5fa613b6bad to your computer and use it in GitHub Desktop.
Save EricRabil/8ddbd03f4a63315e3e40a5fa613b6bad to your computer and use it in GitHub Desktop.
Property wrappers providing access to shared logs identified by StaticStrings
import Foundation
import OSLog
extension StaticString: Hashable {
public static func == (lhs: StaticString, rhs: StaticString) -> Bool {
if lhs.hasPointerRepresentation || rhs.hasPointerRepresentation {
guard lhs.hasPointerRepresentation && rhs.hasPointerRepresentation else {
return false
}
return strcmp(lhs.utf8Start, rhs.utf8Start) == 0
} else {
return lhs.unicodeScalar == rhs.unicodeScalar
}
}
public func hash(into hasher: inout Hasher) {
if hasPointerRepresentation {
withUTF8Buffer {
hasher.combine(bytes: UnsafeRawBufferPointer($0))
}
} else {
unicodeScalar.hash(into: &hasher)
}
}
}
extension String {
init(_ string: StaticString) {
if string.hasPointerRepresentation {
self = NSString(bytesNoCopy: UnsafeMutableRawPointer(mutating: UnsafeRawPointer(string.utf8Start)), length: string.utf8CodeUnitCount, encoding: NSUTF8StringEncoding, freeWhenDone: false)! as String
} else {
self = string.description
}
}
}
struct Loggers {
}
private extension Loggers {
private static var lock: UnsafeMutablePointer<pthread_rwlock_t> = {
let lock = UnsafeMutablePointer<pthread_rwlock_t>.allocate(capacity: 1)
pthread_rwlock_init(lock, nil)
return lock
}()
typealias Logs = [StaticString: Logger]
private static var logs: Logs = [:]
static func withRead<P>(_ callback: (Logs) -> P) -> P {
pthread_rwlock_rdlock(lock)
let result = callback(logs)
pthread_rwlock_unlock(lock)
return result
}
static func withWrite<P>(_ callback: (inout Logs) -> P) -> P {
pthread_rwlock_wrlock(lock)
let result = callback(&logs)
pthread_rwlock_unlock(lock)
return result
}
}
extension Loggers {
static func logger(_ name: StaticString) -> Logger {
if let logger = withRead ({ $0[name] }) {
return logger
}
return withWrite ({
if let logger = $0[name] {
return logger
}
let logger = Logger(subsystem: "com.ericrabil.kctool", category: String(name))
$0[name] = logger
return logger
})
}
}
@propertyWrapper
struct Log {
let name: StaticString
var wrappedValue: Logger {
Loggers.logger(name)
}
init(_ name: StaticString) {
self.name = name
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment