diff options
Diffstat (limited to 'Sources/WmapParser/WmapParser.swift')
| -rw-r--r-- | Sources/WmapParser/WmapParser.swift | 125 |
1 files changed, 63 insertions, 62 deletions
diff --git a/Sources/WmapParser/WmapParser.swift b/Sources/WmapParser/WmapParser.swift index 41843b3..ef203ec 100644 --- a/Sources/WmapParser/WmapParser.swift +++ b/Sources/WmapParser/WmapParser.swift @@ -2,75 +2,76 @@ import Foundation public struct WmapParser { - // Public API ////////////////////////////////////////////////////////////////// + // Public API ////////////////////////////////////////////////////////////////// - /// Parses a wmap source string. - public static func parse(_ source: String) -> Map { - source.utf8.withContiguousStorageIfAvailable { bytes in - parseBytes(bytes) - } ?? parseBytes(Array(source.utf8)) - } - - // Parsers ///////////////////////////////////////////////////////////////////// + /// Parses a wmap source string. + public static func parse(_ source: String) -> Map { + source.utf8.withContiguousStorageIfAvailable { bytes in + parseBytes(bytes) + } ?? parseBytes(Array(source.utf8)) + } - /// Main parsing function, we work on bytes as it's faster. - private static func parseBytes<T: Collection>(_ bytes: T) -> Map where T.Element == UInt8, T.Index == Int { - let estimatedLines = bytes.count / 30 + // Parsers ///////////////////////////////////////////////////////////////////// - var context = LineParserContext( - components: [], - dependencies: [], - keywordContext: KeywordParserContext( - stages: [], - notes: [], - groups: [], - inertias: [], - evolutions: [] - ) - ) + /// Main parsing function, we work on bytes as it's faster. + private static func parseBytes<T: Collection>(_ bytes: T) -> Map + where T.Element == UInt8, T.Index == Int { + let estimatedLines = bytes.count / 30 - context.components.reserveCapacity(estimatedLines) - context.dependencies.reserveCapacity(estimatedLines) - context.keywordContext.notes.reserveCapacity(estimatedLines / 10) - context.keywordContext.stages.reserveCapacity(4) - context.keywordContext.groups.reserveCapacity(estimatedLines / 20) - context.keywordContext.inertias.reserveCapacity(estimatedLines / 20) - context.keywordContext.evolutions.reserveCapacity(estimatedLines / 20) + var context = LineParserContext( + components: [], + dependencies: [], + keywordContext: KeywordParserContext( + stages: [], + notes: [], + groups: [], + inertias: [], + evolutions: [] + ) + ) - var index = 0 - let length = bytes.count + context.components.reserveCapacity(estimatedLines) + context.dependencies.reserveCapacity(estimatedLines) + context.keywordContext.notes.reserveCapacity(estimatedLines / 10) + context.keywordContext.stages.reserveCapacity(4) + context.keywordContext.groups.reserveCapacity(estimatedLines / 20) + context.keywordContext.inertias.reserveCapacity(estimatedLines / 20) + context.keywordContext.evolutions.reserveCapacity(estimatedLines / 20) - while index < length { - guard let (start, end) = extractLine(bytes, &index, length) else { continue } - parseLine(bytes, start, end, &context) - } + var index = 0 + let length = bytes.count - return Map( - components: context.components, - dependencies: context.dependencies, - notes: context.keywordContext.notes, - stages: context.keywordContext.stages, - groups: context.keywordContext.groups, - inertias: context.keywordContext.inertias, - evolutions: context.keywordContext.evolutions - ) + while index < length { + guard let (start, end) = extractLine(bytes, &index, length) else { continue } + parseLine(bytes, start, end, &context) } - /// Given a trimmed line, checks if it's a keyword, dependency or component - /// and parses it. - @inline(__always) - private static func parseLine<T: Collection>( - _ bytes: T, _ start: Int, _ end: Int, - _ context: inout LineParserContext - ) where T.Element == UInt8, T.Index == Int { - if bytes[start] == kOpenSquareBracket { - parseKeywordLine(bytes, start, end, &context.keywordContext) - } else if let separatorIndex = hasDependency(bytes, start, end) { - if let dependency = parseDependency(bytes, start, end, separatorIndex) { - context.dependencies.append(dependency) - } - } else if let component = parseComponent(bytes, start, end) { - context.components.append(component) - } - } + return Map( + components: context.components, + dependencies: context.dependencies, + notes: context.keywordContext.notes, + stages: context.keywordContext.stages, + groups: context.keywordContext.groups, + inertias: context.keywordContext.inertias, + evolutions: context.keywordContext.evolutions + ) + } + + /// Given a trimmed line, checks if it's a keyword, dependency or component + /// and parses it. + @inline(__always) + private static func parseLine<T: Collection>( + _ bytes: T, _ start: Int, _ end: Int, + _ context: inout LineParserContext + ) where T.Element == UInt8, T.Index == Int { + if bytes[start] == kOpenSquareBracket { + parseKeywordLine(bytes, start, end, &context.keywordContext) + } else if let separatorIndex = hasDependency(bytes, start, end) { + if let dependency = parseDependency(bytes, start, end, separatorIndex) { + context.dependencies.append(dependency) + } + } else if let component = parseComponent(bytes, start, end) { + context.components.append(component) + } + } } |