1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-08-15 08:00:31 +03:00

Parse numbers avoiding regex matching

This commit is contained in:
Petrov Anatoly 2020-06-06 01:23:00 +07:00
parent e63e6f2407
commit 1101d4fddc
2 changed files with 57 additions and 34 deletions

View File

@ -1659,30 +1659,27 @@ open class SVGParser {
}
fileprivate func doubleFromString(_ string: String) -> Double? {
if let doubleValue = Double(string) {
return doubleValue
}
if string == "none" {
return 0
}
guard let matcher = SVGParserRegexHelper.getUnitsIdenitifierMatcher() else {
return .none
}
let fullRange = NSRange(location: 0, length: string.count)
if let match = matcher.firstMatch(in: string, options: .reportCompletion, range: fullRange) {
let unitString = (string as NSString).substring(with: match.range(at: 1))
let numberString = String(string.dropLast(unitString.count))
let value = Double(numberString) ?? 0
switch unitString {
case "px" :
return value
default:
print("SVG parsing error. Unit \(unitString) not supported")
return value
}
}
return .none
let scanner = Scanner(string: string)
let value = scanner.scannedDouble()
let unit = scanner.scannedCharacters(from: .unitCharacters)
if !scanner.isAtEnd {
let junk = scanner.scannedUpToCharacters(from: []) ?? ""
print("Found trailing junk \"\(junk)\" in string \"\(string)\".")
return .none
}
switch unit {
case nil, "px":
return value
default:
print("SVG parsing error. Unit \"\(unit ?? "")\" is not supported")
return value
}
}
fileprivate func getDoubleValueFromPercentage(_ element: SWXMLHash.XMLElement, attribute: String) -> Double? {
@ -2189,3 +2186,43 @@ fileprivate enum SVGKeys {
static let color = "color"
static let currentColor = "currentColor"
}
fileprivate extension Scanner {
/// A version of `scanDouble()`, available for an earlier OS.
func scannedDouble() -> Double? {
if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {
return scanDouble()
} else {
var double: Double = 0
return scanDouble(&double) ? double : nil
}
}
/// A version of `scanCharacters(from:)`, available for an earlier OS.
func scannedCharacters(from set: CharacterSet) -> String? {
if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {
return scanCharacters(from: set)
} else {
var string: NSString? = nil
return scanCharacters(from: set, into: &string) ? string as String? : nil
}
}
/// A version of `scanUpToCharacters(from:)`, available for an earlier OS.
func scannedUpToCharacters(from set: CharacterSet) -> String? {
if #available(OSX 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) {
return scanUpToCharacters(from: set)
} else {
var string: NSString? = nil
return scanUpToCharacters(from: set, into: &string) ? string as String? : nil
}
}
}
fileprivate extension CharacterSet {
/// Latin alphabet characters.
static let latinAlphabet = CharacterSet(charactersIn: "a"..."z")
.union(CharacterSet(charactersIn: "A"..."Z"))
static let unitCharacters = CharacterSet.latinAlphabet
}

View File

@ -6,13 +6,11 @@ class SVGParserRegexHelper {
fileprivate static let transformPattern = "\\-?\\d+\\.?\\d*e?\\-?\\d*"
fileprivate static let textElementPattern = "<text.*?>((?s:.*))<\\/text>"
fileprivate static let maskIdenitifierPattern = "url\\(#((?s:.*))\\)"
fileprivate static let unitsIdenitifierPattern = "([a-zA-Z]+)$"
fileprivate static var transformMatcher: NSRegularExpression?
fileprivate static var transformAttributeMatcher: NSRegularExpression?
fileprivate static var textElementMatcher: NSRegularExpression?
fileprivate static var maskIdenitifierMatcher: NSRegularExpression?
fileprivate static var unitsMatcher: NSRegularExpression?
class func getTransformAttributeMatcher() -> NSRegularExpression? {
if self.transformAttributeMatcher == nil {
@ -57,16 +55,4 @@ class SVGParserRegexHelper {
}
return self.maskIdenitifierMatcher
}
class func getUnitsIdenitifierMatcher() -> NSRegularExpression? {
if unitsMatcher == nil {
do {
unitsMatcher = try NSRegularExpression(pattern: unitsIdenitifierPattern, options: .caseInsensitive)
} catch {
}
}
return unitsMatcher
}
}