diff options
Diffstat (limited to 'Sources/WmapParser/Utils.swift')
| -rw-r--r-- | Sources/WmapParser/Utils.swift | 222 |
1 files changed, 112 insertions, 110 deletions
diff --git a/Sources/WmapParser/Utils.swift b/Sources/WmapParser/Utils.swift index 8bea13a..d79578b 100644 --- a/Sources/WmapParser/Utils.swift +++ b/Sources/WmapParser/Utils.swift @@ -1,136 +1,138 @@ -/// Check if a byte is a digit -@inline(__always) -func isDigit(_ byte: UInt8) -> Bool { - byte >= kZero && byte <= kNine -} +extension WmapParser { + /// Check if a byte is a digit + @inline(__always) + static func isDigit(_ byte: UInt8) -> Bool { + byte >= kZero && byte <= kNine + } -/// Looks for x and y separated by a comma. -func parseCoordinates<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> ( - MapPoint, Int -)? -where T.Element == UInt8, T.Index == Int { - var index = skipWhitespace(bytes, end, start) + /// Looks for x and y separated by a comma. + static func parseCoordinates<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> ( + MapPoint, Int + )? + where T.Element == UInt8, T.Index == Int { + var index = skipWhitespace(bytes, end, start) - guard let (xCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { - return nil - } - index = nextIndex + guard let (xCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { + return nil + } + index = nextIndex - guard expectComma(bytes, &index, end) else { return nil } + guard expectComma(bytes, &index, end) else { return nil } - guard let (yCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { - return nil - } - index = nextIndex + guard let (yCoordinate, nextIndex) = parseSingleCoordinate(bytes, index, end) else { + return nil + } + index = nextIndex - guard expectClosingParen(bytes, &index, end) else { return nil } + guard expectClosingParen(bytes, &index, end) else { return nil } - return (MapPoint(xCoordinate: xCoordinate, yCoordinate: yCoordinate), index) -} + return (MapPoint(xCoordinate: xCoordinate, yCoordinate: yCoordinate), index) + } -/// Checks if a candidate for a coordinate is a digit, and parses it. -@inline(__always) -func parseSingleCoordinate<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> (Double, Int)? -where T.Element == UInt8, T.Index == Int { - var index = start - while index < end && (isDigit(bytes[index]) || bytes[index] == 46) { index += 1 } - guard index > start else { return nil } - guard let value = parseDouble(bytes, start, index) else { return nil } - return (value, index) -} + /// Checks if a candidate for a coordinate is a digit, and parses it. + @inline(__always) + static func parseSingleCoordinate<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> (Double, Int)? + where T.Element == UInt8, T.Index == Int { + var index = start + while index < end && (isDigit(bytes[index]) || bytes[index] == 46) { index += 1 } + guard index > start else { return nil } + guard let value = parseDouble(bytes, start, index) else { return nil } + return (value, index) + } -/// Advances the index until we find a comma. -@inline(__always) -func expectComma<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool -where T.Element == UInt8, T.Index == Int { - index = skipWhitespace(bytes, end, index) - guard index < end && bytes[index] == kComma else { return false } - index += 1 - index = skipWhitespace(bytes, end, index) - return true -} + /// Advances the index until we find a comma. + @inline(__always) + static func expectComma<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool + where T.Element == UInt8, T.Index == Int { + index = skipWhitespace(bytes, end, index) + guard index < end && bytes[index] == kComma else { return false } + index += 1 + index = skipWhitespace(bytes, end, index) + return true + } -/// Advances the index until we find a closing parenthesis -@inline(__always) -func expectClosingParen<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool -where T.Element == UInt8, T.Index == Int { - index = skipWhitespace(bytes, end, index) - guard index < end && bytes[index] == kCloseParenthesis else { return false } - index += 1 - return true -} + /// Advances the index until we find a closing parenthesis + @inline(__always) + static func expectClosingParen<T: Collection>(_ bytes: T, _ index: inout Int, _ end: Int) -> Bool + where T.Element == UInt8, T.Index == Int { + index = skipWhitespace(bytes, end, index) + guard index < end && bytes[index] == kCloseParenthesis else { return false } + index += 1 + return true + } -/// Parses a double -@inline(__always) -func parseDouble<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Double? -where T.Element == UInt8, T.Index == Int { - var index = skipWhitespace(bytes, end, start) + /// Parses a double + @inline(__always) + static func parseDouble<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Double? + where T.Element == UInt8, T.Index == Int { + var index = skipWhitespace(bytes, end, start) - let numStart = index - while index < end && (isDigit(bytes[index]) || bytes[index] == kPeriod) { index += 1 } + let numStart = index + while index < end && (isDigit(bytes[index]) || bytes[index] == kPeriod) { index += 1 } - guard index > numStart else { return nil } + guard index > numStart else { return nil } - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - let str = String(decoding: bytes[numStart..<index], as: UTF8.self) - return Double(str) -} + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + let str = String(decoding: bytes[numStart..<index], as: UTF8.self) + return Double(str) + } -/// Advances an index by looking for whitespace left-to-right -func skipWhitespace<T: Collection>(_ bytes: T, _ end: Int, _ start: Int) -> Int -where T.Element == UInt8, T.Index == Int { - var index = start - while index < end && (bytes[index] == kSpace || bytes[index] == kTab) { index += 1 } - return index -} + /// Advances an index by looking for whitespace left-to-right + static func skipWhitespace<T: Collection>(_ bytes: T, _ end: Int, _ start: Int) -> Int + where T.Element == UInt8, T.Index == Int { + var index = start + while index < end && (bytes[index] == kSpace || bytes[index] == kTab) { index += 1 } + return index + } -/// Decreases an index by looking for whitespace right-to-left -func shaveWhitespace<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Int -where T.Element == UInt8, T.Index == Int { - var index = end - while index > start && (bytes[index - 1] == kSpace || bytes[index - 1] == kTab) { index -= 1 } - return index -} + /// Decreases an index by looking for whitespace right-to-left + static func shaveWhitespace<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> Int + where T.Element == UInt8, T.Index == Int { + var index = end + while index > start && (bytes[index - 1] == kSpace || bytes[index - 1] == kTab) { index -= 1 } + return index + } -/// Given the bytes buffer, finds the next non-empty line. -@inline(__always) -func extractLine<T: Collection>(_ bytes: T, _ index: inout Int, _ length: Int) -> ( - Int, Int -)? -where T.Element == UInt8, T.Index == Int { - while index < length && (bytes[index] == kNewline || bytes[index] == kCarriageReturn) { - index += 1 - } - let lineStart = index + /// Given the bytes buffer, finds the next non-empty line. + @inline(__always) + static func extractLine<T: Collection>(_ bytes: T, _ index: inout Int, _ length: Int) -> ( + Int, Int + )? + where T.Element == UInt8, T.Index == Int { + while index < length && (bytes[index] == kNewline || bytes[index] == kCarriageReturn) { + index += 1 + } + let lineStart = index - while index < length && bytes[index] != kNewline && bytes[index] != kCarriageReturn { index += 1 } - if lineStart == index { return nil } + while index < length && bytes[index] != kNewline && bytes[index] != kCarriageReturn { index += 1 } + if lineStart == index { return nil } - var start = lineStart - var end = index + var start = lineStart + var end = index - start = skipWhitespace(bytes, end, start) - end = shaveWhitespace(bytes, start, end) + start = skipWhitespace(bytes, end, start) + end = shaveWhitespace(bytes, start, end) - if start == end { return nil } + if start == end { return nil } - return (start, end) -} + return (start, end) + } -/// Trims a byte collection and returns a string -@inline(__always) -func extractTrimmedString<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> String? -where T.Element == UInt8, T.Index == Int { - var trimStart = start - var trimEnd = end + /// Trims a byte collection and returns a string + @inline(__always) + static func extractTrimmedString<T: Collection>(_ bytes: T, _ start: Int, _ end: Int) -> String? + where T.Element == UInt8, T.Index == Int { + var trimStart = start + var trimEnd = end - trimStart = skipWhitespace(bytes, trimEnd, trimStart) - trimEnd = shaveWhitespace(bytes, trimStart, trimEnd) + trimStart = skipWhitespace(bytes, trimEnd, trimStart) + trimEnd = shaveWhitespace(bytes, trimStart, trimEnd) - guard trimStart < trimEnd else { return nil } + guard trimStart < trimEnd else { return nil } - // Why not String(data:encoding:)? This is much faster. - // swiftlint:disable:next optional_data_string_conversion - return String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) + // Why not String(data:encoding:)? This is much faster. + // swiftlint:disable:next optional_data_string_conversion + return String(decoding: bytes[trimStart..<trimEnd], as: UTF8.self) + } } |