Skip to content

Commit 00fe58d

Browse files
phimagee-marchand
authored andcommitted
Add some serialisation functions to PropertyList too
1 parent 8cec2af commit 00fe58d

File tree

6 files changed

+165
-96
lines changed

6 files changed

+165
-96
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
.build
1+
.build
2+
.swiftpm

Sources/OpenStepSerializer.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ class OpenStepSerializer {
1414
let projectFile: XcodeProj
1515
let lineEnding: String
1616

17-
init(projectName: String, lineEnding: String = "\r\n", projectFile: XcodeProj) {
17+
init(projectName: String, lineEnding: String? = "\r\n", projectFile: XcodeProj) {
1818
self.projectName = projectName
19-
self.lineEnding = lineEnding
19+
self.lineEnding = lineEnding ?? "\r\n"
2020
self.projectFile = projectFile
2121
}
2222

@@ -67,7 +67,7 @@ class OpenStepSerializer {
6767
}
6868
#if os(Linux)
6969
let row: String
70-
if let dict = val as? [AnyHashable: Any], dict.isEmpty {
70+
if let dict = val as? [AnyHashable: Any], dict.isEmpty {
7171
row = "\(key) = {\n}\(comment);" // print on linux give [:] ...
7272
} else {
7373
row = "\(key) = \(val)\(comment);"

Sources/PropertyList.swift

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//
2+
// PropertyList.swift
3+
//
4+
//
5+
// Created by emarchand on 22/10/2022.
6+
//
7+
8+
import Foundation
9+
10+
open class PropertyList {
11+
12+
public enum Format {
13+
case binary
14+
case xml
15+
case json
16+
case openStep
17+
18+
public func toPropertyListformat() -> PropertyListSerialization.PropertyListFormat? {
19+
switch self {
20+
case .binary:
21+
return .binary
22+
case .xml:
23+
return .xml
24+
case .openStep:
25+
return .openStep
26+
case .json:
27+
return nil
28+
}
29+
}
30+
31+
public init(_ format: PropertyListSerialization.PropertyListFormat) {
32+
switch format {
33+
case .binary:
34+
self = .binary
35+
case .xml:
36+
self = .xml
37+
case .openStep:
38+
self = .openStep
39+
@unknown default:
40+
fatalError("unknown format")
41+
}
42+
}
43+
44+
public init?(_ format: PropertyListSerialization.PropertyListFormat?) {
45+
if let format = format {
46+
self.init(format)
47+
} else {
48+
return nil
49+
}
50+
}
51+
52+
public init?(string: String) {
53+
switch string.lowercased() {
54+
case "openstep":
55+
self = .openStep
56+
case "xml", "xml1":
57+
self = .xml
58+
case "json":
59+
self = .json
60+
case "binary", "binary1":
61+
self = .binary
62+
default:
63+
return nil
64+
}
65+
}
66+
67+
}
68+
69+
public let dict: PBXObject.Fields
70+
public let format: Format
71+
72+
public init(dict: PBXObject.Fields, format: Format) throws {
73+
self.dict = dict
74+
self.format = format
75+
}
76+
77+
public convenience init(propertyListData data: Data) throws {
78+
let format: Format
79+
let obj: Any
80+
if data.first == 123 { // start with {
81+
obj = try JSONSerialization.jsonObject(with: data)
82+
format = .json
83+
} else {
84+
var propertyListFormat: PropertyListSerialization.PropertyListFormat = .binary
85+
obj = try PropertyListSerialization.propertyList(from: data, options: [], format: &propertyListFormat)
86+
format = .init(propertyListFormat)
87+
}
88+
89+
guard let dict = obj as? PBXObject.Fields else {
90+
throw XcodeProjError.invalidData(object: obj)
91+
}
92+
93+
try self.init(dict: dict, format: format)
94+
}
95+
96+
public convenience init(url: URL) throws {
97+
assert(url.isFileURL)
98+
do {
99+
let data = try Data(contentsOf: url)
100+
try self.init(propertyListData: data)
101+
} catch let error as XcodeProjError {
102+
throw error
103+
} catch {
104+
throw XcodeProjError.failedToReadFile(error: error)
105+
}
106+
}
107+
108+
// MARK: - Write
109+
public func write(to url: URL,
110+
format: Format,
111+
atomic: Bool = true) throws {
112+
if format == .openStep {
113+
throw XcodeProjError.notSupported
114+
} else if let propertyListformat = format.toPropertyListformat() {
115+
let data = try PropertyListSerialization.data(
116+
fromPropertyList: dict,
117+
format: propertyListformat,
118+
options: 0)
119+
#if os(Linux)
120+
try data.write(to: url, options: []) // error no attomic on linux
121+
#else
122+
try data.write(to: url, options: atomic ? [.atomicWrite] : [])
123+
#endif
124+
} else if format == .json {
125+
let data = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
126+
#if os(Linux)
127+
try data.write(to: url, options: []) // error no attomic on linux
128+
#else
129+
try data.write(to: url, options: atomic ? [.atomicWrite] : [])
130+
#endif
131+
}
132+
}
133+
134+
public func data() throws -> Data {
135+
if format == .openStep {
136+
throw XcodeProjError.notSupported
137+
} else if let propertyListformat = format.toPropertyListformat() {
138+
return try PropertyListSerialization.data(fromPropertyList: dict, format: propertyListformat, options: 0)
139+
} else if format == .json {
140+
return try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
141+
}
142+
return Data()
143+
}
144+
145+
}

Sources/XcodeProj+Serialization.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ import Foundation
1010

1111
extension XcodeProj {
1212

13-
public func write(to url: URL, format: Format? = nil,
14-
projectName: String? = nil, lineEnding: String? = nil, atomic: Bool = true) throws {
13+
public func write(to url: URL,
14+
format: Format? = nil,
15+
projectName: String? = nil,
16+
lineEnding: String? = nil,
17+
atomic: Bool = true) throws {
1518
let pbxprojURL: URL
1619
let name: String
1720
if url.isDirectoryURL {
@@ -36,16 +39,17 @@ extension XcodeProj {
3639
if format == .openStep {
3740
let serializer = OpenStepSerializer(projectName: name, lineEnding: lineEnding, projectFile: self)
3841
try serializer.serialize().write(to: pbxprojURL, atomically: atomic, encoding: .utf8)
39-
}
40-
else if let propertyListformat = format.toPropertyListformat() {
41-
let data = try PropertyListSerialization.data(fromPropertyList: dict, format: propertyListformat, options: 0)
42+
} else if let propertyListformat = format.toPropertyListformat() {
43+
let data = try PropertyListSerialization.data(
44+
fromPropertyList: dict,
45+
format: propertyListformat,
46+
options: 0)
4247
#if os(Linux)
4348
try data.write(to: pbxprojURL, options: []) // error no attomic on linux
4449
#else
4550
try data.write(to: pbxprojURL, options: atomic ? [.atomicWrite] : [])
4651
#endif
47-
}
48-
else if format == .json {
52+
} else if format == .json {
4953
let data = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
5054
#if os(Linux)
5155
try data.write(to: pbxprojURL, options: []) // error no attomic on linux
@@ -62,8 +66,7 @@ extension XcodeProj {
6266
return try serializer.serialize().data(using: .utf8) ?? Data()
6367
} else if let propertyListformat = format.toPropertyListformat() {
6468
return try PropertyListSerialization.data(fromPropertyList: dict, format: propertyListformat, options: 0)
65-
}
66-
else if format == .json {
69+
} else if format == .json {
6770
return try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
6871
}
6972
return Data() // must not occurs

Sources/XcodeProj.swift

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -8,88 +8,6 @@
88

99
import Foundation
1010

11-
open class PropertyList {
12-
13-
public enum Format {
14-
case binary
15-
case xml
16-
case json
17-
case openStep
18-
19-
public func toPropertyListformat() -> PropertyListSerialization.PropertyListFormat? {
20-
switch self {
21-
case .binary:
22-
return .binary
23-
case .xml:
24-
return .xml
25-
case .openStep:
26-
return .openStep
27-
case .json:
28-
return nil
29-
}
30-
}
31-
32-
public init(_ format: PropertyListSerialization.PropertyListFormat) {
33-
switch format {
34-
case .binary:
35-
self = .binary
36-
case .xml:
37-
self = .xml
38-
case .openStep:
39-
self = .openStep
40-
}
41-
}
42-
43-
public init?(_ format: PropertyListSerialization.PropertyListFormat?) {
44-
if let format = format {
45-
self.init(format)
46-
} else {
47-
return nil
48-
}
49-
}
50-
}
51-
52-
public let dict: PBXObject.Fields
53-
public let format: Format
54-
55-
public init(dict: PBXObject.Fields, format: Format) throws {
56-
self.dict = dict
57-
self.format = format
58-
}
59-
60-
public convenience init(propertyListData data: Data) throws {
61-
let format: Format
62-
let obj: Any
63-
if data.first == 123 { // start with {
64-
obj = try JSONSerialization.jsonObject(with: data)
65-
format = .json
66-
} else {
67-
var propertyListFormat: PropertyListSerialization.PropertyListFormat = .binary
68-
obj = try PropertyListSerialization.propertyList(from: data, options: [], format: &propertyListFormat)
69-
format = .init(propertyListFormat)
70-
}
71-
72-
guard let dict = obj as? PBXObject.Fields else {
73-
throw XcodeProjError.invalidData(object: obj)
74-
}
75-
76-
try self.init(dict: dict, format: format)
77-
}
78-
79-
public convenience init(url: URL) throws {
80-
assert(url.isFileURL)
81-
do {
82-
let data = try Data(contentsOf: url)
83-
try self.init(propertyListData: data)
84-
} catch let error as XcodeProjError {
85-
throw error
86-
} catch {
87-
throw XcodeProjError.failedToReadFile(error: error)
88-
}
89-
}
90-
91-
}
92-
9311
public class XcodeProj: PropertyList {
9412

9513
public static let pbxprojFileExtension = "pbxproj"
@@ -150,7 +68,6 @@ public class XcodeProj: PropertyList {
15068

15169
}
15270

153-
15471
// MARK: init
15572
public convenience init(url: URL) throws {
15673
assert(url.isFileURL)

Sources/XcodeProjError.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,7 @@ public enum XcodeProjError: Error {
2222
// object missing
2323
case objectMissing(key: String, expectedType: Isa?)
2424

25+
// not supported
26+
case notSupported
27+
2528
}

0 commit comments

Comments
 (0)