Skip to content

Commit 7ea4528

Browse files
Improve performance of prettyPrintVersions()
Change the implementation of prettyPrintVersions() to find, process, and replace the substring to be updated rather than splitting, iterating, and joining the string. Resolves #52
1 parent 9781b8e commit 7ea4528

File tree

1 file changed

+27
-37
lines changed

1 file changed

+27
-37
lines changed

Sources/EvolutionMetadataExtraction/Utilities/FileUtilities.swift

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -96,48 +96,38 @@ enum JSONRewriter {
9696
}
9797

9898
static func prettyPrintVersions(_ sourceString: String) -> String {
99-
100-
var processedString = ""
101-
var processingVersionsField = false
10299

103-
var itemCount = 0
104-
let maxPerLine = 10
105-
for line in sourceString.split(separator: "\n") {
100+
let versionsListRegex = /"implementationVersions" : \[\n(?<versionsList>(?:\s*"(?:(?:(?:\d+\.)+\d+)|Next)",?\n)*)/
101+
var processedString: String
102+
103+
if let match = sourceString.firstMatch(of: versionsListRegex) {
104+
// Copy versions list string
105+
var versionsString = String(match.output.versionsList)
106+
107+
// Remove newlines and spaces for every nth item in versions array
108+
let maxPerLine = 10
109+
let maxReplacements = maxPerLine - 1
110+
let endlineRegex = /\n\s+/ // One or more whitespace intentionally prevents last item from matching
106111

107-
if line.contains(/"implementationVersions" :/) {
108-
processedString += line + "\n"
109-
processingVersionsField = true
110-
continue
112+
var first = true
113+
var startIndex = versionsString.startIndex
114+
while let foundRange = versionsString[startIndex..<versionsString.endIndex].firstRange(of: endlineRegex) {
115+
if first { first = false } // Find and replace endline of first list item
116+
else { startIndex = foundRange.upperBound } // Skip the next found endline leaving the line break in place
117+
let subrange = startIndex..<versionsString.endIndex
118+
versionsString = versionsString.replacing(endlineRegex, with: " ", subrange: subrange, maxReplacements: maxReplacements)
111119
}
120+
121+
// Replace versions list
122+
let replacementRange = match.output.versionsList.startIndex..<match.output.versionsList.endIndex
123+
processedString = sourceString.replacingCharacters(in: replacementRange, with: versionsString)
124+
125+
processedString.replace("\n\n", with: "\n") // Replace blank lines in entire string
112126

113-
if processingVersionsField {
114-
if line.contains(/],/) {
115-
processedString += "\n" + line + "\n"
116-
processingVersionsField = false
117-
itemCount = 0
118-
continue
119-
} else {
120-
// Use first array item as-is
121-
if itemCount == 0 {
122-
processedString += line
123-
}
124-
// When we are at the max per line, put this array element on a new line
125-
else if itemCount == maxPerLine {
126-
itemCount = 0
127-
processedString += "\n" + line
128-
}
129-
// Other array items on same line separated by a space
130-
// The original line already contains the separating comma
131-
else {
132-
processedString += " " + line.trimmingCharacters(in: .whitespacesAndNewlines)
133-
}
134-
itemCount += 1
135-
}
136-
} else {
137-
processedString += line + "\n"
138-
}
127+
} else {
128+
processedString = sourceString
139129
}
140-
130+
processedString.append("\n") // Add newline at end of string
141131
return processedString
142132
}
143133
}

0 commit comments

Comments
 (0)