Skip to content

Commit

Permalink
Merge pull request #7 from g-Off/xcode-10
Browse files Browse the repository at this point in the history
Xcode 10
  • Loading branch information
g-Off authored Dec 5, 2018
2 parents c4215ec + f93921c commit a312bdc
Show file tree
Hide file tree
Showing 26 changed files with 297 additions and 255 deletions.
4 changes: 2 additions & 2 deletions Sources/XcodeProject/Archiving/PBXPListArchiver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ public final class PBXPListArchiver {
}

final class ObjectVisitor {
private var objectMap: [PBXObject.ID: PBXObject] = [:]
private var visited = Set<PBXObject.ID>()
private var objectMap: [PBXGlobalID: PBXObject] = [:]
private var visited = Set<PBXGlobalID>()

func visit(object: PBXObject?, where predicate: @escaping (_ object: PBXObject) -> Bool = { _ in return true}) {
guard let object = object else { return }
Expand Down
10 changes: 5 additions & 5 deletions Sources/XcodeProject/Archiving/PBXPListUnarchiver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ class ObjectCache {
self.types = types
}

internal var objects: [PBXObject.ID: PBXObject] = [:]
internal var objects: [PBXGlobalID: PBXObject] = [:]

func object<T: PBXObject>(for globalID: PBXObject.ID?) -> T? {
func object<T: PBXObject>(for globalID: PBXGlobalID?) -> T? {
guard let globalID = globalID else { return nil }
return cached(globalID: globalID, create: true) as? T
}

private func cached(globalID: PBXObject.ID, create: Bool = false) -> PBXObject? {
private func cached(globalID: PBXGlobalID, create: Bool = false) -> PBXObject? {
if let existing = objects[globalID] {
return existing
} else if create {
Expand All @@ -35,7 +35,7 @@ class ObjectCache {
return nil
}

private func createObject(globalID: PBXObject.ID) -> PBXObject? {
private func createObject(globalID: PBXGlobalID) -> PBXObject? {
guard let objectPlist = plist[globalID.rawValue] as? [String: Any] else { return nil }
guard let isa = objectPlist["isa"] as? String else { fatalError() }

Expand All @@ -51,7 +51,7 @@ class ObjectCache {
return object
}

private func setCached(object: PBXObject?, for globalID: PBXObject.ID) {
private func setCached(object: PBXObject?, for globalID: PBXGlobalID) {
guard let object = object else {
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public extension PBXGroup {
currentGroup = currentGroup.addGroup(pathComponent: $0)
}
}
let fileReference = PBXFileReference(globalID: PBXObject.ID(), path: filePathComponents.last)
let fileReference = PBXFileReference(globalID: PBXGlobalID(), path: filePathComponents.last)
currentGroup.add(child: fileReference)
return fileReference
}

@discardableResult
func addGroup(pathComponent: String) -> PBXGroup {
let group = PBXGroup(globalID: PBXObject.ID(), name: nil, path: pathComponent, sourceTree: .group)
let group = PBXGroup(globalID: PBXGlobalID(), name: nil, path: pathComponent, sourceTree: .group)
children.append(group)
return group
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
//

public extension PBXProject {
func generateGlobalId() -> PBXObject.ID {
var objectId = PBXObject.ID()
func generateGlobalId() -> PBXGlobalID {
var objectId = PBXGlobalID()
while objects[objectId] != nil {
objectId = PBXObject.ID()
objectId = PBXGlobalID()
}
return objectId
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public class PBXBuildPhase: PBXObject {
}
self._name = plist["name"]?.string
self.files = files.compactMap {
let file: PBXBuildFile? = objectCache.object(for: PBXObject.ID(rawValue: $0))
let file: PBXBuildFile? = objectCache.object(for: PBXGlobalID(rawValue: $0))
return file
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/XcodeProject/Objects/PBXBuildFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ public final class PBXBuildFile: PBXObject {
}
var settings: [String: Any]?

public convenience init(globalID: PBXObject.ID, fileReference: PBXReference) {
public convenience init(globalID: PBXGlobalID, fileReference: PBXReference) {
self.init(globalID: globalID)
fileRef = fileReference
}

override func update(with plist: PropertyList, objectCache: ObjectCache) {
super.update(with: plist, objectCache: objectCache)
self.fileRef = objectCache.object(for: PBXObject.ID(rawValue: plist["fileRef"]?.string))
self.fileRef = objectCache.object(for: PBXGlobalID(rawValue: plist["fileRef"]?.string))
self.settings = plist["settings"]?.dictionary
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/XcodeProject/Objects/PBXContainerItemProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class PBXContainerItemProxy: PBXObject {
super.update(with: plist, objectCache: objectCache)

guard
let containerPortal = objectCache.object(for: PBXObject.ID(rawValue: plist["containerPortal"]?.string)),
let containerPortal = objectCache.object(for: PBXGlobalID(rawValue: plist["containerPortal"]?.string)),
let proxyType = ProxyType(string: plist["proxyType"]?.string),
let remoteGlobalIDString = plist["remoteGlobalIDString"]?.string,
let remoteInfo = plist["remoteInfo"]?.string
Expand Down
124 changes: 124 additions & 0 deletions Sources/XcodeProject/Objects/PBXGlobalID+Generator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//
// PBXGlobalID+Generator.swift
// XcodeProject
//
// Created by Geoffrey Foster on 2018-12-02.
//

import Foundation

extension PBXGlobalID {
struct Generator {
private struct GlobalIdentifier: CustomStringConvertible {
let userHash: UInt8
let pidByte: UInt8
var random: UInt16
var time: UInt32
let zero: UInt8 = 0
let hostShift: UInt8
let hostHigh: UInt8
let hostLow: UInt8

var description: String {
let components = [
userHash.hexRepresentation,
pidByte.hexRepresentation,
random.hexRepresentation,
time.hexRepresentation,
zero.hexRepresentation,
hostShift.hexRepresentation,
hostHigh.hexRepresentation,
hostLow.hexRepresentation,
]
return components.joined()
}
}

private var gid: GlobalIdentifier

private var randomSequence: UInt16 = 0
private let referenceDateGenerator: () -> Date

private var lastTime: UInt32 = 0
private var firstSequence: UInt16 = 0

init(userName: String = NSUserName(), processId: pid_t = getpid(), random: inout RandomNumberGenerator, referenceDateGenerator: @escaping () -> Date = Generator.referenceDate) {
self.referenceDateGenerator = referenceDateGenerator

var hostId: UInt32 = UInt32(gethostid())
if hostId == 0 {
hostId = random.next()
}
self.gid = GlobalIdentifier(
userHash: Generator.userHash(userName: userName),
pidByte: UInt8(truncatingIfNeeded: processId),
random: random.next(),
time: 0,
hostShift: UInt8(truncatingIfNeeded: (hostId >> 0x10) & 0xff),
hostHigh: UInt8(truncatingIfNeeded: (hostId & 0xff00) >> 0x8),
hostLow: UInt8(truncatingIfNeeded: hostId & 0xff)
)
}

mutating func next() -> String {
let randomValue = gid.random + 1

let time = UInt32(referenceDateGenerator().timeIntervalSinceReferenceDate)
if time > lastTime {
firstSequence = randomValue
lastTime = time
} else if firstSequence == randomValue {
lastTime += 1
}

gid.random = randomValue
gid.time = lastTime

return gid.description
}

static func referenceDate() -> Date {
return Date()
}

static func userHash(userName: String) -> UInt8 {
func hash(character: UnicodeScalar) -> UInt32 {
let uppercaseA: UnicodeScalar = "A"
let uppercaseZ: UnicodeScalar = "Z"
let lowercaseA: UnicodeScalar = "a"
let zero: UnicodeScalar = "0"
switch character {
case "A"..."Z":
return character.value - uppercaseA.value
case "a"..."z":
return character.value - lowercaseA.value
case "0"..."9":
return uppercaseZ.value - uppercaseA.value + 1 + (UInt32(character.value - zero.value) % 5)
default:
return 31
}
}

var userHash: UInt32 = 0
var hashValue: UInt32 = 0
userName.unicodeScalars.map { hash(character: $0) }.forEach {
var h = $0
if h != 0 {
h = ((h << hashValue) >> 8) | (h << hashValue)
}
hashValue = (hashValue + 5) & 7
userHash = userHash ^ h
}
return UInt8(truncatingIfNeeded: userHash)
}
}
}

extension BinaryInteger {
var hexRepresentation: String {
let hex = String(self, radix: 16, uppercase: true)
let byteCount = bitWidth / 4
let padding = max(byteCount - hex.count, 0)
return String(repeating: "0", count: padding) + hex
}
}
54 changes: 54 additions & 0 deletions Sources/XcodeProject/Objects/PBXGlobalID.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// PBXGlobalID.swift
// XcodeProject
//
// Created by Geoffrey Foster on 2018-12-02.
//

import Foundation

public struct PBXGlobalID: RawRepresentable {
public let rawValue: String

public init(rawValue: String) {
self.rawValue = rawValue
}

public init?(rawValue: String?) {
guard let rawValue = rawValue else { return nil }
self.init(rawValue: rawValue)
}

public init() {
self.rawValue = PBXGlobalID.generator.next()
}

static func ids(from strings: [String]?) -> [PBXGlobalID]? {
return strings?.compactMap { return PBXGlobalID(rawValue: $0) }
}

private static var randomNumberGenerator: RandomNumberGenerator = SystemRandomNumberGenerator()
private static var generator: PBXGlobalID.Generator = PBXGlobalID.Generator(random: &randomNumberGenerator)
}

extension PBXGlobalID: Hashable {
public var hashValue: Int {
return rawValue.hashValue
}

public static func ==(lhs: PBXGlobalID, rhs: PBXGlobalID) -> Bool {
return lhs.rawValue == rhs.rawValue
}
}

extension PBXGlobalID: Comparable {
public static func <(lhs: PBXGlobalID, rhs: PBXGlobalID) -> Bool {
return lhs.rawValue < rhs.rawValue
}
}

extension PropertyList {
var globalID: PBXGlobalID? {
return PBXGlobalID(rawValue: self.string)
}
}
Loading

0 comments on commit a312bdc

Please sign in to comment.