diff options
Diffstat (limited to 'Sources/WmapParser/Utils.swift')
| -rw-r--r-- | Sources/WmapParser/Utils.swift | 226 |
1 files changed, 115 insertions, 111 deletions
diff --git a/Sources/WmapParser/Utils.swift b/Sources/WmapParser/Utils.swift index d79578b..4886eb3 100644 --- a/Sources/WmapParser/Utils.swift +++ b/Sources/WmapParser/Utils.swift @@ -1,138 +1,142 @@ extension WmapParser { - /// Check if a byte is a digit - @inline(__always) - static func isDigit(_ byte: UInt8) -> Bool { - byte >= kZero && byte <= kNine - } + /// 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. - 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) + /// 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) - 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) - } + /// 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) - 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 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) - 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 - } + /// 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) - 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) + /// 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 - 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 - } + /// 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 - 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 - } + /// 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) - 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 + /// 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) - 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 + /// 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) + } } |