@@ -13,6 +13,7 @@ import func POSIX.getenv
13
13
14
14
enum PkgConfigError : ErrorProtocol {
15
15
case CouldNotFindConfigFile
16
+ case ParsingError
16
17
}
17
18
18
19
struct PkgConfig {
@@ -91,13 +92,13 @@ struct PkgConfigParser {
91
92
let equalsIndex = line. characters. index ( of: " = " ) !
92
93
let name = line [ line. startIndex..< equalsIndex]
93
94
let value = line [ equalsIndex. successor ( ) ..< line. endIndex]
94
- variables [ name] = resolveVariables ( value)
95
+ variables [ name] = try resolveVariables ( value)
95
96
} else if line. hasPrefix ( " Requires: " ) {
96
97
dependencies = parseDependencies ( value ( line: line) )
97
98
} else if line. hasPrefix ( " Libs: " ) {
98
- libs = resolveVariables ( value ( line: line) ) . chomp ( )
99
+ libs = try resolveVariables ( value ( line: line) ) . chomp ( )
99
100
} else if line. hasPrefix ( " Cflags: " ) {
100
- cFlags = resolveVariables ( value ( line: line) ) . chomp ( )
101
+ cFlags = try resolveVariables ( value ( line: line) ) . chomp ( )
101
102
}
102
103
}
103
104
}
@@ -121,21 +122,40 @@ struct PkgConfigParser {
121
122
return deps
122
123
}
123
124
124
- private func resolveVariables( _ line: String ) -> String {
125
- func resolve( _ string: String ) -> String {
126
- var resolvedString = string
127
- guard let dollar = resolvedString. characters. index ( of: " $ " ) else { return string }
128
- guard let variableEndIndex = resolvedString. characters. index ( of: " } " ) else { return string }
129
- let variable = string [ dollar. successor ( ) . successor ( ) ..< variableEndIndex]
130
- let value = variables [ variable] !
131
- resolvedString = resolvedString [ resolvedString. startIndex..< dollar] + value + resolvedString[ variableEndIndex. successor ( ) ..< resolvedString. endIndex]
132
- return resolvedString
125
+ /// Variables occur in form of ${variableName}, we search for a variable linearly
126
+ /// in the string and if found, lookup the value of the variable in our dictionary and
127
+ /// replace the variable name with its value.
128
+ private func resolveVariables( _ line: String ) throws -> String {
129
+ typealias StringIndex = String . CharacterView . Index
130
+
131
+ // Returns variable name, start index and end index of a variable in a string if present.
132
+ // We make sure it of form ${name} otherwise it is not a variable.
133
+ func findVariable( _ fragment: String ) -> ( name: String , startIndex: StringIndex , endIndex: StringIndex ) ? {
134
+ guard let dollar = fragment. characters. index ( of: " $ " ) else { return nil }
135
+ guard dollar != fragment. endIndex && fragment. characters [ dollar. successor ( ) ] == " { " else { return nil }
136
+ guard let variableEndIndex = fragment. characters. index ( of: " } " ) else { return nil }
137
+ return ( fragment [ dollar. successor ( ) . successor ( ) ..< variableEndIndex] , dollar, variableEndIndex)
133
138
}
134
- var resolved = line
135
- while resolved. characters. contains ( " $ " ) {
136
- resolved = resolve ( resolved)
139
+
140
+ var result = " "
141
+ var fragment = line
142
+ while !fragment. isEmpty {
143
+ // Look for a variable in our current fragment.
144
+ if let variable = findVariable ( fragment) {
145
+ // Append the contents before the variable.
146
+ result += fragment [ fragment. characters. startIndex..< variable. startIndex]
147
+ guard let variableValue = variables [ variable. name] else { throw PkgConfigError . ParsingError }
148
+ // Append the value of the variable.
149
+ result += variableValue
150
+ // Update the fragment with post variable string.
151
+ fragment = fragment [ variable. endIndex. successor ( ) ..< fragment. characters. endIndex]
152
+ } else {
153
+ // No variable found, just append rest of the fragment to result.
154
+ result += fragment
155
+ fragment = " "
156
+ }
137
157
}
138
- return resolved
158
+ return result
139
159
}
140
160
141
161
private func value( line: String ) -> String {
0 commit comments