Skip to content

Commit

Permalink
Swift 6 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ikhvorost committed Feb 8, 2025
1 parent a9b873b commit a14065c
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 148 deletions.
51 changes: 51 additions & 0 deletions [email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// swift-tools-version: 6.0
//
// Package.swift
//
// Created by Iurii Khvorost <[email protected]> on 2025/02/04.
// Copyright © 2025 Iurii Khvorost. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

import PackageDescription

let package = Package(
name: "DLog",
platforms: [
.iOS(.v12),
.macOS(.v10_15),
.tvOS(.v12),
.visionOS(.v1),
.watchOS(.v5)
],
products: [
.library(name: "DLog", targets: ["DLog"]),
.library(name: "DLogObjC", targets: ["DLogObjC"]),
.executable(name: "NetConsole", targets: ["NetConsole"])
],
targets: [
.target(name: "DLog"),
.target(name: "DLogObjC", dependencies: ["DLog"]),
.executableTarget(name: "NetConsole"),
.testTarget(name: "DLogTests", dependencies: ["DLog"]),
.testTarget(name: "DLogTestsObjC", dependencies: ["DLogObjC"])
],
swiftLanguageModes: [.v6]
)
53 changes: 53 additions & 0 deletions Sources/DLog/Atomic.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//
// Atomic.swift
//
// Created by Iurii Khvorost <[email protected]> on 2021/02/04.
// Copyright © 2021 Iurii Khvorost. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

import Foundation

@discardableResult
func synchronized<T : AnyObject, U>(_ obj: T, closure: () -> U) -> U {
objc_sync_enter(obj)
defer {
objc_sync_exit(obj)
}
return closure()
}

@propertyWrapper
public final class Atomic<T> {
private var value: T

public init(wrappedValue value: T) {
self.value = value
}

public var wrappedValue: T {
get {
synchronized(self) { value }
}
set {
synchronized(self) { value = newValue }
}
}
}
7 changes: 4 additions & 3 deletions Sources/DLog/DLog.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Foundation

/// The central class to emit log messages to specified outputs using one of the methods corresponding to a log level.
///
public class DLog: Log {
public final class DLog: Log {

let output: LogOutput?

Expand All @@ -38,8 +38,9 @@ public class DLog: Log {
///
/// let logger = DLog.disabled
///
@objc
public static let disabled = DLog(nil)
// TODO: fix
//@objc
//public static let disabled = DLog(nil)

/// Creates a logger object that assigns log messages to a specified category.
///
Expand Down
2 changes: 1 addition & 1 deletion Sources/DLog/Dynamic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ typealias Swift_Demangle = @convention(c) (_ mangledName: UnsafePointer<UInt8>?,
_ outputBufferSize: UnsafeMutablePointer<Int>?,
_ flags: UInt32) -> UnsafeMutablePointer<Int8>?
/// Dynamic shared object
class Dynamic {
actor Dynamic {

// Constants
static let dso = UnsafeMutableRawPointer(mutating: #dsohandle)
Expand Down
2 changes: 1 addition & 1 deletion Sources/DLog/LogConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extension OptionSet where RawValue == Int {
}

/// Indicates which info from the logger should be used.
public struct LogOptions: OptionSet {
public struct LogOptions: OptionSet, Sendable {
/// The corresponding value of the raw type.
public let rawValue: Int

Expand Down
137 changes: 69 additions & 68 deletions Sources/DLog/LogFormat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,59 @@
import Foundation
import Network


#if swift(>=6.0)
extension ByteCountFormatter: @unchecked @retroactive Sendable {}
#endif

// Formatters

fileprivate let dateFormatter = DateFormatter()
fileprivate let byteCountFormatter = ByteCountFormatter()
fileprivate let numberFormatter = NumberFormatter()
fileprivate let dateComponentsFormatter: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.year, .month, .weekOfMonth, .day, .hour, .minute, .second]
return formatter
}()

@discardableResult
func synchronized<T : AnyObject, U>(_ obj: T, closure: () -> U) -> U {
objc_sync_enter(obj)
defer {
objc_sync_exit(obj)
fileprivate struct Formatter {

static private let date = DateFormatter()
static func date(value: Date, dateStyle: DateFormatter.Style, timeStyle: DateFormatter.Style, locale: Locale?) -> String {
synchronized(date) {
date.dateStyle = dateStyle
date.timeStyle = timeStyle
date.locale = locale
return date.string(from: value)
}
}
static func date(value: Date, dateFormat: String) -> String {
synchronized(date) {
date.dateFormat = dateFormat
return date.string(from: value)
}
}

static private let byteCount = ByteCountFormatter()
static func byteCount(value: Int64, countStyle: ByteCountFormatter.CountStyle, allowedUnits: ByteCountFormatter.Units) -> String {
synchronized(byteCount) {
byteCount.countStyle = countStyle
byteCount.allowedUnits = allowedUnits
return byteCount.string(fromByteCount: value)
}
}

static private let number = NumberFormatter()
static func number(value: NSNumber, style: NumberFormatter.Style, locale: Locale?) -> String {
synchronized(number) {
number.locale = locale
number.numberStyle = style
return number.string(from: value)!
}
}


static private let dateComponents: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.year, .month, .weekOfMonth, .day, .hour, .minute, .second]
return formatter
}()
static func dateComponents(timeInterval: TimeInterval, unitsStyle: DateComponentsFormatter.UnitsStyle) -> String {
synchronized(dateComponents) {
dateComponents.unitsStyle = unitsStyle
return dateComponents.string(from: timeInterval) ?? ""
}
}
return closure()
}

fileprivate func insertMs(time: String, sec: String, ms: String) -> String {
Expand All @@ -59,10 +93,7 @@ fileprivate func insertMs(time: String, sec: String, ms: String) -> String {
}

func stringFromTimeInterval(_ timeInterval: TimeInterval, unitsStyle: DateComponentsFormatter.UnitsStyle = .abbreviated) -> String {
let time: String = synchronized(dateComponentsFormatter) {
dateComponentsFormatter.unitsStyle = unitsStyle
return dateComponentsFormatter.string(from: timeInterval) ?? ""
}
let time = Formatter.dateComponents(timeInterval: timeInterval, unitsStyle: unitsStyle)

guard let fraction = String(format: "%.3f", timeInterval).split(separator: ".").last, fraction != "000" else {
return time
Expand All @@ -83,11 +114,8 @@ func stringFromTimeInterval(_ timeInterval: TimeInterval, unitsStyle: DateCompon
return insertMs(time: time, sec: " second", ms: ms)

case .spellOut:
let text: String = synchronized(numberFormatter) {
numberFormatter.numberStyle = .spellOut
let value = Double(fraction)!
return numberFormatter.string(from: NSNumber(value: value))!
}
let value = NSNumber(value: Double(fraction)!)
let text = Formatter.number(value: value, style: .spellOut, locale: nil)
return "\(time), \(text) milliseconds"

case .brief:
Expand Down Expand Up @@ -116,25 +144,18 @@ public enum LogDateFormatting {
case dateCustom(format: String)

func string(from value: Date) -> String {
synchronized(dateFormatter) {
switch self {

case let .date(dateStyle, timeStyle, locale):
dateFormatter.dateStyle = dateStyle
dateFormatter.timeStyle = timeStyle
dateFormatter.locale = locale
return dateFormatter.string(from: value)

case let .dateCustom(format):
dateFormatter.dateFormat = format
return dateFormatter.string(from: value)
}
return switch self {
case let .date(dateStyle, timeStyle, locale):
Formatter.date(value: value, dateStyle: dateStyle, timeStyle: timeStyle, locale: locale)

case let .dateCustom(format):
Formatter.date(value: value, dateFormat: format)
}
}
}

/// Format options for integers.
public enum LogIntFormatting {
public enum LogIntFormatting: Sendable {
/// Displays an integer value in binary format.
case binary

Expand Down Expand Up @@ -223,18 +244,11 @@ public enum LogIntFormatting {
return "\(prefix)\(hex)"

case let .byteCount(countStyle, allowedUnits):
return synchronized(byteCountFormatter) {
byteCountFormatter.countStyle = countStyle
byteCountFormatter.allowedUnits = allowedUnits
return byteCountFormatter.string(fromByteCount: Int64(value))
}
return Formatter.byteCount(value: Int64(value), countStyle: countStyle, allowedUnits: allowedUnits)

case let .number(style, locale):
return synchronized(numberFormatter) {
numberFormatter.locale = locale
numberFormatter.numberStyle = style
return numberFormatter.string(from: NSNumber(value: Int64(value)))!
}
let value = NSNumber(value: Int64(value))
return Formatter.number(value: value, style: style, locale: locale)

case .httpStatusCode:
return "HTTP \(value) \(HTTPURLResponse.localizedString(forStatusCode: Int(value)))"
Expand All @@ -249,18 +263,13 @@ public enum LogIntFormatting {

case let .date(dateStyle, timeStyle, locale):
let date = Date(timeIntervalSince1970: Double(value))
return synchronized(dateFormatter) {
dateFormatter.dateStyle = dateStyle
dateFormatter.timeStyle = timeStyle
dateFormatter.locale = locale
return dateFormatter.string(from: date)
}
return Formatter.date(value: date, dateStyle: dateStyle, timeStyle: timeStyle, locale: locale)
}
}
}

/// Format options for floating-point numbers.
public enum LogFloatFormatting {
public enum LogFloatFormatting: Sendable {
/// Displays a floating-point value in fprintf's `%f` format with specified precision.
///
/// - Parameters:
Expand Down Expand Up @@ -357,23 +366,15 @@ public enum LogFloatFormatting {
: String(format: "%g", doubleValue)

case let .number(style, locale):
return synchronized(numberFormatter) {
numberFormatter.locale = locale
numberFormatter.numberStyle = style
return numberFormatter.string(from: NSNumber(value: doubleValue))!
}
let value = NSNumber(value: doubleValue)
return Formatter.number(value: value, style: style, locale: locale)

case let .time(unitsStyle):
return stringFromTimeInterval(doubleValue, unitsStyle: unitsStyle)

case let .date(dateStyle, timeStyle, locale):
let date = Date(timeIntervalSince1970: doubleValue)
return synchronized(dateFormatter) {
dateFormatter.dateStyle = dateStyle
dateFormatter.timeStyle = timeStyle
dateFormatter.locale = locale
return dateFormatter.string(from: date)
}
return Formatter.date(value: date, dateStyle: dateStyle, timeStyle: timeStyle, locale: locale)
}
}
}
Expand Down
Loading

0 comments on commit a14065c

Please sign in to comment.